├── .circleci └── config.yml ├── .gitignore ├── .midje.clj ├── LICENSE ├── Makefile ├── NEWS.md ├── README.md ├── TODO ├── aliases ├── build │ └── phone_number │ │ └── build │ │ └── main.clj ├── codox │ └── phone_number │ │ └── codox │ │ └── main.clj ├── nrepl │ └── nrepl.clj └── rebel │ └── phone_number │ └── rebel │ └── main.clj ├── bin ├── build ├── docs ├── lint ├── nrepl ├── repl ├── test └── test-notifier ├── circle.yml ├── deps.edn ├── dev └── src │ ├── infra.clj │ ├── phone_number │ └── generator.clj │ └── user.clj ├── doc ├── 10_introduction.md ├── 30_specs.md └── 40_development.md ├── docs ├── .gitignore ├── 10_introduction.html ├── 30_specs.html ├── 40_development.html ├── LICENSE ├── css │ ├── default.css │ ├── highlight.css │ └── randomseed.css ├── index.html ├── js │ ├── highlight.min.js │ ├── jquery.min.js │ └── page_effects.js ├── phone-number.calling-code.html ├── phone-number.core.html ├── phone-number.cost.html ├── phone-number.country-code.html ├── phone-number.db.html ├── phone-number.format.html ├── phone-number.html ├── phone-number.leniency.html ├── phone-number.locale.html ├── phone-number.match.html ├── phone-number.net-code.html ├── phone-number.region.html ├── phone-number.spec.html ├── phone-number.type.html ├── phone-number.tz-format.html └── phone-number.util.html ├── phone-number.jar.asc ├── pom.xml ├── pom.xml.asc ├── resources └── codox │ └── theme │ └── randomseed │ ├── css │ └── randomseed.css │ └── theme.edn ├── src ├── phone_number.clj └── phone_number │ ├── calling_code.clj │ ├── core.clj │ ├── cost.clj │ ├── country_code.clj │ ├── db.clj │ ├── dialing_region.clj │ ├── format.clj │ ├── leniency.clj │ ├── locale.clj │ ├── match.clj │ ├── net_code.clj │ ├── region.clj │ ├── sample.clj │ ├── short.clj │ ├── spec.clj │ ├── type.clj │ ├── tz_format.clj │ └── util.clj ├── test └── phone_number │ └── core_test.clj └── tests.edn /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # Clojure CircleCI 2.0 configuration file 2 | # 3 | # Check https://circleci.com/docs/2.0/language-clojure/ for more details 4 | # 5 | version: 2 6 | jobs: 7 | build: 8 | docker: 9 | # specify the version you desire here 10 | - image: cimg/clojure:1.11.1 11 | 12 | # Specify service dependencies here if necessary 13 | # CircleCI maintains a library of pre-built images 14 | # documented at https://circleci.com/docs/2.0/circleci-images/ 15 | # - image: circleci/postgres:9.4 16 | 17 | working_directory: ~/repo 18 | 19 | environment: 20 | # Customize the JVM maximum heap limit 21 | JVM_OPTS: -Xmx3200m 22 | 23 | steps: 24 | - checkout 25 | 26 | # Download and cache dependencies 27 | - restore_cache: 28 | keys: 29 | - v1-dependencies-{{ checksum "deps.edn" }} 30 | # fallback to using the latest cache if no exact match is found 31 | - v1-dependencies- 32 | 33 | - run: sudo apt-get install -y make 34 | - run: make test 35 | 36 | - save_cache: 37 | paths: 38 | - ~/.m2 39 | key: v1-dependencies-{{ checksum "deps.edn" }} 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /classes 3 | /checkouts 4 | *.jar 5 | *.class 6 | /.lein-* 7 | /.rebel_* 8 | /.nrepl-port 9 | .DS_Store 10 | .hgignore 11 | .hg/ 12 | gh-pages 13 | .cpcache/ 14 | /DELETE_ME 15 | /.dir-locals.el 16 | /.shadow-cljs/ 17 | /todo.org 18 | /project.clj.bak 19 | /bin/test-cljs 20 | node_modules/ 21 | /cljs-test-runner-out 22 | pom.xml.versionsBackup 23 | -------------------------------------------------------------------------------- /.midje.clj: -------------------------------------------------------------------------------- 1 | (change-defaults :emitter 'midje.emission.plugins.default 2 | :print-level :print-facts) 3 | (change-defaults 4 | :visible-future false) 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | 167 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | APPNAME = "phone-number" 2 | VERSION = "8.13.6-3" 3 | 4 | .PHONY: watch default docs deploy test test-clj sig jar pom clean tag 5 | 6 | default: docs 7 | 8 | lint: 9 | bin/lint 10 | 11 | docs: 12 | bin/docs "$(VERSION)" 13 | 14 | push-docs: 15 | git subtree push --prefix=docs docs master 16 | 17 | test-clj: 18 | bin/test --no-profiling 19 | 20 | test: 21 | @$(MAKE) test-clj 22 | 23 | pom: pom.xml 24 | clojure -Spom && awk 'NF > 0' pom.xml > pom.new.xml && mv -f pom.new.xml pom.xml 25 | mvn versions:set versions:commit -DnewVersion="$(VERSION)" versions:set-scm-tag -DnewTag="$(VERSION)" 26 | rm -f pom.xml.asc 27 | 28 | $(APPNAME).jar: pom.xml 29 | bin/build 30 | 31 | jar: $(APPNAME).jar 32 | 33 | sig: pom.xml 34 | rm -f pom.xml.asc 35 | gpg2 --armor --detach-sig pom.xml 36 | 37 | tag: pom.xml 38 | git tag -s "$(VERSION)" -m "Release $(VERSION)" 39 | 40 | deploy: 41 | @$(MAKE) clean 42 | @$(MAKE) pom 43 | @$(MAKE) jar 44 | mvn gpg:sign-and-deploy-file -Dfile=$(APPNAME).jar -DrepositoryId=clojars -Durl=https://clojars.org/repo -DpomFile=pom.xml 45 | 46 | clean: 47 | rm -f $(APPNAME).jar pom.xml.asc 48 | 49 | .PHONY: list 50 | list: 51 | @$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$@$$' | xargs 52 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # History of phone-number releases 2 | 3 | ## 8.13.6-3 (2023-02-26) 4 | 5 | - Improvements: 6 | 7 | * Speed optimizations (type hints, referential equality). 8 | 9 | ## 8.13.6-2 (2023-02-24) 10 | 11 | - Improvements: 12 | 13 | * Memoization support for parsing phone numbers as strings. 14 | * Improved assertion function `phone-number.core/valid-input?`. 15 | 16 | ## 8.13.6-1 (2023-02-11) 17 | 18 | - Improvements: 19 | 20 | * Added `phone-number.core/number-optraw`. 21 | * `phone-number.core/noraw` now creates a copy and strips raw input when 22 | a `PhoneNumber` is given. 23 | * Inline documentation strings edited. 24 | 25 | ## 8.13.6-0 (2023-02-11) 26 | 27 | - Improvements: 28 | 29 | * Libphonenumber version bump. 30 | * Added printing method. 31 | 32 | ## 8.13.2-0 (2022-12-13) 33 | 34 | - Improvements: 35 | 36 | * Libphonenumber version bump. 37 | 38 | ## 8.12.52-0 (2022-07-29) 39 | 40 | - Improvements: 41 | 42 | * Improved building and documentation generating code. 43 | * Separated nREPL from REPL (development mode). 44 | * Syntactical cleanups. 45 | * Libphonenumber dependency updated to match version 8.12.52. 46 | * Geocoder dependency updated to match version 2.188. 47 | * Prefixmapper dependency updated to match version 2.188. 48 | * Carrier dependency updated to match version 1.178. 49 | * Development dependencies updated to match their newest versions. 50 | 51 | ## 8.12.28-0, 8.12.28-1 (2021-07-21) 52 | 53 | - Improvements: 54 | 55 | * Libphonenumber version bump. 56 | 57 | - Bug fixes: 58 | 59 | * Removed development dependencies (orchestra) from `spec.clj`. 60 | * Moved development file `generator.clj` to `dev/src`. 61 | 62 | ## 8.12.21-0 (2021-04-19) 63 | 64 | - Improvements: 65 | 66 | * Libphonenumber version bump. 67 | * Removed reflection warnings. 68 | 69 | ## 8.12.16-1 (2021-01-31) 70 | 71 | - Improvements: 72 | 73 | * Added some missing validators and databases for argument processing 74 | * Samplers corrected to use -arg versions of databases 75 | * Added support for pseudo-region `:phone-number.region/world` for non-geographic numbers 76 | * Created `phone-number.db` with cross-databases: 77 | * Regions to types 78 | * Types to regions 79 | * Regions to calling codes 80 | * Calling codes to regions 81 | * Calling codes to types 82 | * Types to calling codes 83 | * New functions in core: 84 | * `phone-number.core/calling-code-prefix` 85 | * `phone-number.core/regions-for-calling-code` 86 | * `phone-number.core/region-for-calling-code` 87 | * `phone-number.core/calling-codes-for-region` 88 | * Improved main phone numbers generator 89 | (random regions and calling codes are picked up from valid sets for randomly 90 | generated types) 91 | * Specs divided into 3 groups: 92 | * Input data specs 93 | * Generic specs (outputs, common data structures) 94 | * Internal specs (arguments, properties) 95 | * Removed legacy support for accepting region codes as enum type values 96 | * Shuffling functions from `phone-number.util` are now short-circuiting on `nil` values 97 | * Assertion errors reporting improved 98 | * Development process now uses Eastwood linter 99 | 100 | - Bug fixes: 101 | 102 | * Function for building phone numbers from maps now properly handles invalid data 103 | * Removed unneeded `:phone-number.region/unknown` 104 | * Removed global network calling codes from `phone-number.country-code/all` and 105 | related 106 | * Documentation corrected in some places 107 | 108 | ## 8.12.16-0 (2021-01-23) 109 | 110 | - Improvements: 111 | 112 | * Libphonenumber dependency updated to match version 8.12.16 113 | * Geocoder dependency updated to match version 2.152 114 | * Carrier dependency updated to match version 1.142 115 | * Development dependencies updated to match newest versions 116 | 117 | - Bug fixes: 118 | 119 | * Some local tests (run from REPL) are now using proper default region 120 | 121 | ## 8.12.4-3 (2021-01-23) 122 | 123 | - Improvements: 124 | 125 | * More relaxed arities (usually allowing to skip region code) 126 | * Locale support moved to a separate file (with parsing and validation) 127 | * Added leniency support (`phone-number/leniency`, `phone-number.core/leniencies`) 128 | * Added leniency and max-tries support to `phone-number.core/find-numbers` 129 | * Added tests for `phone-number.core/find-numbers` 130 | * Specs updated to reflect changes 131 | * Documentation updated 132 | 133 | - Bug fixes: 134 | 135 | * Fixed typo in spec for `phone-number.core/time-zones` return value 136 | * Fixed setting the default value of dialing region in `phone-number.core/info` 137 | when main arity is called by other arities. 138 | 139 | ## 8.12.4-2 (2020-06-27) 140 | 141 | - Improvements: 142 | 143 | * Type-hinted `locale-specification` arguments as keywords 144 | * Improved fetching of the required data from phone numbers expressed as maps: 145 | * `phone-number.core/raw-input` 146 | * `phone-number.core/valid-input?` 147 | * Changed from accepting phone numbers only as strings to polymorphic: 148 | * `phone-number.core/short-emergency?` 149 | * `phone-number.core/short-to-emergency?` 150 | * Added namespaces and namespace aliases for shorter keywords notation: 151 | * `phone-number` 152 | * `phone-number.short` 153 | * `phone-number.sample` 154 | * `phone-number.dialing-region` 155 | * `phone-number.arg` (specs only) 156 | * `phone-number.args` (specs only) 157 | * `phone-number.prop` (specs only) 158 | 159 | - Bug fixes: 160 | 161 | * Fixed spec for `phone-number.core/raw-input` 162 | 163 | ## 8.12.4-1 (2020-06-24) 164 | 165 | - BREAKING CHANGES: 166 | 167 | * Calling region (code) is now renamed to dialing region (code) 168 | * `:phone-number.calling-region` is now `:phone-number.dialing-region` 169 | * `:phone-number.short/dialing-region` property is replaced by 170 | `:phone-number/dialing-region` 171 | * `phone-number.core/valid-for-region?` is now deprecated in favor of `phone-number.core/valid?` 172 | 173 | - Improvements: 174 | 175 | * Default dialing region support with `phone-number.core/*default-dialing-region*` 176 | * Dialing region derivation support with `phone-number.core/*info-dialing-region-derived*` 177 | * Improved support for maps as phone numbers (incl. dialing region retention) 178 | * Added validation for locale specification (`phone-number.util/valid-locale?`) 179 | * Samples generator now uses custom, simpler phone number parser 180 | * Additional arities in `phone-number.format/global?` and 181 | `phone-number.format/regional?` 182 | * Input validation is more relaxed (no strict asserts based on first digits) 183 | * Added `phone-number.core/has-raw-input?` 184 | * Added `phone-number.core/numeric` 185 | * Added utility functions in `phone-number.util`: 186 | - `count-digits` 187 | - `char-ranges->set` 188 | - `available-locales` 189 | * Specs updated 190 | * Tests updated 191 | * Generative testing based on generators and specs 192 | 193 | - Bug fixes: 194 | 195 | * Proper handling of corner cases (nil punning) at: 196 | - `phone-number.core/short-info` 197 | - `phone-number.core/time-zones-all-formats` 198 | - `phone-number.core/all-formats` 199 | - `phone-number.core/has-calling-code?` 200 | - `phone-number.core/raw-input` 201 | 202 | ## 8.12.4-0 (2020-06-11) 203 | 204 | - Initial release. 205 | 206 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | - tests 2 | -------------------------------------------------------------------------------- /aliases/build/phone_number/build/main.clj: -------------------------------------------------------------------------------- 1 | (ns phone-number.build.main 2 | 3 | (:require [clojure.java.io :as io] 4 | [clojure.data.xml :as xml] 5 | [clojure.tools.build.api :as b] 6 | [juxt.pack.api :as pack])) 7 | 8 | (defn jar 9 | [_] 10 | (pack/library 11 | {:basis (b/create-basis) 12 | :path "phone-number.jar" 13 | :lib 'io.randomseed/phone-number 14 | :pom (java.io.ByteArrayInputStream. 15 | (.getBytes 16 | (xml/emit-str 17 | (xml/parse (io/reader "pom.xml"))) 18 | "UTF-8"))})) 19 | 20 | (defn -main 21 | [& args] 22 | (jar nil)) 23 | -------------------------------------------------------------------------------- /aliases/codox/phone_number/codox/main.clj: -------------------------------------------------------------------------------- 1 | (ns phone-number.codox.main 2 | (:require [codox.main :as c] 3 | [clojure.java.io :as io] 4 | [clojure.edn :as edn] 5 | [clojure.tools.deps.alpha :as deps] 6 | [clojure.string :as str])) 7 | 8 | (defn- read-deps 9 | [] 10 | (:project-edn (deps/find-edn-maps))) 11 | 12 | (defn- get-options [deps & more] 13 | (let [key (or (first more) :codox) 14 | version (or (second more) "0.0.0") 15 | codox (key deps) 16 | userdir (System/getProperty "user.dir")] 17 | (merge {:source-paths (:paths deps ["src"]) 18 | :root-path (:root-path deps userdir) 19 | :output-path (str (io/file (:target deps userdir) "docs"))} 20 | codox 21 | {:name (str/capitalize (:name codox (:name deps))) 22 | :license (:license codox (:license deps)) 23 | :package (:package codox (:license deps)) 24 | :description (:description codox (:description deps)) 25 | :version (or version (:version codox (:version deps)))}))) 26 | 27 | (defn codox 28 | "Generate API documentation from source code." 29 | [key version] 30 | (let [version (when version (str version)) 31 | deps (read-deps) 32 | options (get-options deps key version)] 33 | (codox.main/generate-docs options) 34 | (shutdown-agents) 35 | (println "Generated HTML docs in" (:output-path options)))) 36 | 37 | (defn -main 38 | [& args] 39 | (codox :codox (first args))) 40 | -------------------------------------------------------------------------------- /aliases/nrepl/nrepl.clj: -------------------------------------------------------------------------------- 1 | (ns ^{:clojure.tools.namespace.repl/load false} nrepl 2 | (:require 3 | [nrepl.server :refer [start-server stop-server]] 4 | [cider.nrepl] 5 | ;;[refactor-nrepl.middleware :as refactor.nrepl] 6 | [io.aviso.ansi] 7 | [puget.printer :refer [cprint]])) 8 | 9 | (defn start-nrepl-old 10 | [opts] 11 | (let [server 12 | (start-server 13 | :port (:port opts) 14 | :handler 15 | (apply nrepl.server/default-handler 16 | (conj (map #'cider.nrepl/resolve-or-fail cider.nrepl/cider-middleware) 17 | ;; #'refactor.nrepl/wrap-refactor 18 | )))] 19 | (spit ".nrepl-port" (:port server)) 20 | (println (io.aviso.ansi/yellow (str "[phone-number] nREPL client can be connected to port " (:port server)))) 21 | server)) 22 | 23 | (defn nrepl-handler [] 24 | (ns-resolve 'cider.nrepl 'cider-nrepl-handler)) 25 | 26 | (defn start-nrepl 27 | [opts] 28 | (let [server (start-server :port (:port opts) :handler (nrepl-handler))] 29 | (println (io.aviso.ansi/yellow (str "[phone-number] nREPL client can be connected to port " (:port server)))) 30 | server)) 31 | 32 | (println "[phone-number] Starting nREPL server") 33 | 34 | (def server (start-nrepl {:port 5610})) 35 | -------------------------------------------------------------------------------- /aliases/rebel/phone_number/rebel/main.clj: -------------------------------------------------------------------------------- 1 | (ns phone-number.rebel.main 2 | (:require 3 | rebel-readline.clojure.main 4 | rebel-readline.core 5 | io.aviso.ansi 6 | puget.printer)) 7 | 8 | (defn -main 9 | [& args] 10 | (rebel-readline.core/ensure-terminal 11 | (rebel-readline.clojure.main/repl 12 | :init (fn [] 13 | (try 14 | (println "[phone-number] Loading Clojure code, please wait...") 15 | (require 'user) 16 | (in-ns 'user) 17 | (catch Exception e 18 | (.printStackTrace e) 19 | (println "[phone-number] Failed to require user, this usually means there was a syntax error. See exception above."))))))) 20 | -------------------------------------------------------------------------------- /bin/build: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "[phone-number] Building JAR, please wait..." 4 | 5 | clojure -M:build 6 | -------------------------------------------------------------------------------- /bin/docs: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "[phone-number] Building docs, please wait..." 4 | 5 | clojure -M:docs "${1}" 6 | -------------------------------------------------------------------------------- /bin/lint: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "[phone-number] Running Eastwood lint tool..." 4 | 5 | clojure -A:eastwood 6 | -------------------------------------------------------------------------------- /bin/nrepl: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "[phone-number] Starting development environment, please wait..." 4 | 5 | clojure -A:dev:dev-nrepl:dev-rebel 6 | -------------------------------------------------------------------------------- /bin/repl: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "[phone-number] Starting development environment, please wait..." 4 | 5 | clojure -A:dev:dev-rebel 6 | -------------------------------------------------------------------------------- /bin/test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | test -f secrets.env && . secrets.env 4 | clojure -A:test "$@" 5 | -------------------------------------------------------------------------------- /bin/test-notifier: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | terminal-notifier -message "${1}" -title "${2}" -appIcon "${3}" 4 | -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | test: 2 | override: 3 | - 'make test' 4 | -------------------------------------------------------------------------------- /deps.edn: -------------------------------------------------------------------------------- 1 | { 2 | :paths ["src" "resources"] 3 | 4 | :deps {trptr/java-wrapper {:mvn/version "0.2.3"} 5 | malabarba/lazy-map {:mvn/version "1.3"} 6 | org.clojure/core.memoize {:mvn/version "1.0.257"} 7 | com.googlecode.libphonenumber/libphonenumber {:mvn/version "8.13.6"} 8 | com.googlecode.libphonenumber/geocoder {:mvn/version "2.200"} 9 | com.googlecode.libphonenumber/carrier {:mvn/version "1.190"} 10 | com.googlecode.libphonenumber/prefixmapper {:mvn/version "2.200"}} 11 | 12 | :aliases {:dev {:extra-deps {org.clojure/tools.namespace {:mvn/version "1.1.0"} 13 | org.clojure/tools.deps.alpha {:mvn/version "0.9.857"} 14 | org.clojure/spec.alpha {:mvn/version "0.2.194"} 15 | org.clojure/test.check {:mvn/version "1.1.1"} 16 | orchestra/orchestra {:mvn/version "2021.01.01-1"} 17 | expound/expound {:mvn/version "0.8.7"} 18 | io.aviso/pretty {:mvn/version "1.1.1"} 19 | midje/midje {:mvn/version "1.10.5"} 20 | lambdaisland/kaocha {:mvn/version "1.69.1069"} 21 | lambdaisland/kaocha-midje {:mvn/version "0.0-5"} 22 | lambdaisland/kaocha-cloverage {:mvn/version "1.0.75"} 23 | spyscope/spyscope {:mvn/version "0.1.6"} 24 | fipp/fipp {:mvn/version "0.6.23"} 25 | cljfmt/cljfmt {:mvn/version "0.6.4"} 26 | ns-tracker/ns-tracker {:mvn/version "0.4.0"} 27 | mvxcvi/puget {:mvn/version "1.3.1"} 28 | org.slf4j/slf4j-simple {:mvn/version "2.0.0-alpha7"}} 29 | :extra-paths ["dev/src" "test"] 30 | :jvm-opts ["-Dclojure.spec.compile-asserts=true"]} 31 | :test {:extra-paths ["test"] 32 | :extra-deps {org.clojure/test.check {:mvn/version "1.1.1"} 33 | io.aviso/pretty {:mvn/version "1.1.1"} 34 | midje/midje {:mvn/version "1.10.5"} 35 | orchestra/orchestra {:mvn/version "2021.01.01-1"} 36 | expound/expound {:mvn/version "0.8.7"} 37 | lambdaisland/kaocha {:mvn/version "1.69.1069"} 38 | lambdaisland/kaocha-midje {:mvn/version "0.0-5"} 39 | lambdaisland/kaocha-cloverage {:mvn/version "1.0.75"} 40 | org.slf4j/slf4j-simple {:mvn/version "2.0.0-alpha7"}} 41 | :main-opts ["-m" "kaocha.runner", 42 | "--config-file" "tests.edn", 43 | "--stc-num-tests" "100" 44 | "--stc-instrumentation" 45 | "--stc-asserts"] 46 | :jvm-opts ["-Xmx512m"]} 47 | :eastwood {:main-opts ["-m" "eastwood.lint" {:source-paths ["src"]}] 48 | :extra-deps {org.clojure/test.check {:mvn/version "1.1.1"} 49 | io.aviso/pretty {:mvn/version "1.1.1"} 50 | midje/midje {:mvn/version "1.10.5"} 51 | orchestra/orchestra {:mvn/version "2021.01.01-1"} 52 | expound/expound {:mvn/version "0.8.7"} 53 | org.clojure/tools.namespace {:mvn/version "1.1.0"} 54 | org.clojure/tools.deps.alpha {:mvn/version "0.9.857"} 55 | org.clojure/spec.alpha {:mvn/version "0.2.194"} 56 | jonase/eastwood {:mvn/version "0.3.13"}}} 57 | :docs {:extra-paths ["aliases/codox"] 58 | :extra-deps {org.clojure/tools.deps.alpha {:mvn/version "0.9.857"} 59 | org.clojure/spec.alpha {:mvn/version "0.2.194"} 60 | org.clojure/test.check {:mvn/version "1.1.1"} 61 | orchestra/orchestra {:mvn/version "2021.01.01-1"} 62 | expound/expound {:mvn/version "0.8.7"} 63 | codox/codox {:mvn/version "0.10.8"}} 64 | :main-opts ["-m" "phone-number.codox.main"]} 65 | :build {:paths ["."] 66 | :extra-paths ["aliases/build"] 67 | :deps {io.github.juxt/pack.alpha {:git/sha "9fd4a63ddeec3bedcbc819422de5a40ccb9eb8c9"} 68 | io.github.clojure/tools.build {:git/tag "v0.7.4" :git/sha "ac442da"} 69 | org.clojure/data.zip {:mvn/version "1.0.0"} 70 | org.clojure/data.xml {:mvn/version "0.2.0-alpha6"}} 71 | :ns-default phone-number.build.main 72 | :main-opts ["-m" "phone-number.build.main"]} 73 | :dev-nrepl {:jvm-opts ["-Dnrepl.load=true"] 74 | :extra-paths ["aliases/nrepl"] 75 | :extra-deps {cider/cider-nrepl {:mvn/version "0.25.9"} 76 | ;;refactor-nrepl {:mvn/version "2.3.1"} 77 | cider/piggieback {:mvn/version "0.5.2"} 78 | nrepl/nrepl {:mvn/version "0.8.3"} 79 | kaocha-nrepl/kaocha-nrepl {:mvn/version "1.0.3"} 80 | mvxcvi/puget {:mvn/version "1.3.1"} 81 | org.clojure/tools.nrepl {:mvn/version "0.2.13"}}} 82 | :cider-clj {:extra-paths ["aliases/nrepl"] 83 | :extra-deps {cider/cider-nrepl {:mvn/version "0.25.9"} 84 | cider/piggieback {:mvn/version "0.5.2"} 85 | nrepl/nrepl {:mvn/version "0.8.3"} 86 | kaocha-nrepl/kaocha-nrepl {:mvn/version "1.0.3"} 87 | mvxcvi/puget {:mvn/version "1.3.1"} 88 | org.clojure/tools.nrepl {:mvn/version "0.2.13"}} 89 | :main-opts ["-m" "nrepl.cmdline" "--middleware" "[cider.nrepl/cider-middleware]"]} 90 | :dev-rebel {:extra-paths ["aliases/rebel"] 91 | :extra-deps {com.bhauman/rebel-readline {:mvn/version "0.1.4"} 92 | com.bhauman/rebel-readline-cljs {:mvn/version "0.1.4"} 93 | io.aviso/pretty {:mvn/version "1.1.1"} 94 | mvxcvi/puget {:mvn/version "1.3.1"}} 95 | :main-opts ["-m" "phone-number.rebel.main"]}} 96 | :codox {:name "phone-number" 97 | :description "Generation, validation and inspection of phone numbers" 98 | :license "GNU Lesser General Public License 3.0" 99 | :package io.randomseed/phone-number 100 | :output-path "docs" 101 | :source-uri "https://github.com/randomseed-io/phone-number/tree/{version}/{filepath}#L{line}" 102 | :metadata {:doc/format :markdown} 103 | :themes [:default :randomseed]}} 104 | -------------------------------------------------------------------------------- /dev/src/infra.clj: -------------------------------------------------------------------------------- 1 | (ns infra) 2 | 3 | ;; (defonce nrepl (start-nrepl)) 4 | -------------------------------------------------------------------------------- /dev/src/phone_number/generator.clj: -------------------------------------------------------------------------------- 1 | (ns 2 | 3 | ^{:doc "Sample data generator interface for phone-number library." 4 | :author "Paweł Wilk" 5 | :added "8.12.4-0" 6 | :no-doc true} 7 | 8 | phone-number.generator 9 | 10 | (:require [phone-number.core :as phone] 11 | [clojure.test.check.rose-tree :as rose] 12 | [clojure.test.check.generators :as gens]) 13 | 14 | (:import [java.util Random])) 15 | 16 | (def phone-number 17 | (gens/no-shrink 18 | (clojure.test.check.generators/->Generator 19 | (fn [^Random rng _] 20 | (rose/make-rose 21 | (phone/generate nil nil phone/valid? nil nil (.nextLong ^Random rng)) 22 | []))))) 23 | -------------------------------------------------------------------------------- /dev/src/user.clj: -------------------------------------------------------------------------------- 1 | (ns user 2 | (:require 3 | [clojure.spec.alpha :as s] 4 | [orchestra.spec.test :as st] 5 | [clojure.spec.test.alpha :as cst] 6 | [clojure.spec.gen.alpha :as gen] 7 | [clojure.repl :refer :all] 8 | [clojure.tools.namespace.repl :refer [refresh 9 | refresh-all]] 10 | [expound.alpha :as expound] 11 | [phone-number.core :as phone] 12 | [phone-number.util :as util] 13 | [phone-number.spec :as spec] 14 | [phone-number.db :as db] 15 | [phone-number.region :as region] 16 | [phone-number.type :as type] 17 | 18 | [puget.printer :refer [cprint]] 19 | [midje.repl :refer :all] 20 | [kaocha.repl :refer :all] 21 | [infra]) 22 | 23 | (:import [com.google.i18n.phonenumbers 24 | Phonenumber$PhoneNumber 25 | ShortNumberInfo 26 | geocoding.PhoneNumberOfflineGeocoder 27 | PhoneNumberToCarrierMapper 28 | PhoneNumberToTimeZonesMapper 29 | NumberParseException])) 30 | 31 | (set! *warn-on-reflection* true) 32 | 33 | (alter-var-root 34 | #'s/*explain-out* 35 | (constantly 36 | (expound/custom-printer {:show-valid-values? false 37 | :print-specs? true 38 | :theme :figwheel-theme}))) 39 | 40 | (when (System/getProperty "nrepl.load") 41 | (require 'nrepl)) 42 | 43 | (st/instrument) 44 | 45 | (defn test-all [] 46 | (refresh) 47 | (cst/with-instrument-disabled 48 | (binding [phone/*default-dialing-region* :phone-number.region/us] 49 | (load-facts :print-facts)))) 50 | 51 | (alter-var-root #'*warn-on-reflection* 52 | (constantly true) 53 | (when (thread-bound? #'*warn-on-reflection*) 54 | (set! *warn-on-reflection* true))) 55 | 56 | (comment 57 | (refresh-all) 58 | (cst/with-instrument-disabled (test-all)) 59 | (cst/with-instrument-disabled (run-all)) 60 | ) 61 | -------------------------------------------------------------------------------- /doc/30_specs.md: -------------------------------------------------------------------------------- 1 | # Specs and checks 2 | 3 | ## Predicates 4 | 5 | The phone-number provides many predicate functions that can be used to check for 6 | certain properties of phone numbers. These include: 7 | 8 | | Function Name | Description | 9 | |-----------------------------------------------------|-----------------------------------------------------------| 10 | | [`core/valid-input?`](phone-number.core.html#var-valid-input.3F) | Checks if a value can possibly be used as a phone number | 11 | | [`core/valid?`](phone-number.core.html#var-valid.3F) | Checks if a phone numer is valid | 12 | | [`core/invalid?`](phone-number.core.html#var-invalid.3F) | Checks if a phone numer is invalid | 13 | | [`core/possible?`](phone-number.core.html#var-possible.3F) | Checks if a phone numer is a possible number | 14 | | [`core/impossible?`](phone-number.core.html#var-impossible.3F) | Checks if a phone numer is an impossible number | 15 | | [`core/native?`](phone-number.core.html#var-native.3F) | Checks if a phone numer is in a native format (`PhoneNumber`) | 16 | | [`core/has-raw-input?`](phone-number.core.html#var-has-raw-input.3F) | Checks if a phone numer contains the retained raw input | 17 | | [`core/geographical?`](phone-number.core.html#var-geographical.3F) | Checks if a phone numer identifies a line with some geographical location | 18 | | [`core/short-possible?`](phone-number.core.html#var-short-possible.3F) | Checks if a phone numer is in a possible short number | 19 | | [`core/short-valid?`](phone-number.core.html#var-short-valid.3F) | Checks if a phone numer is in a valid short number | 20 | | [`core/short-emergency?`](phone-number.core.html#var-short-emergency.3F) | Checks if a phone numer is in an emergency number | 21 | | [`core/short-to-emergency?`](phone-number.core.html#var-short-to-emergency.3F) | Checks if a phone numer can be used to connect to an emergency | 22 | | [`core/short-to-emergency?`](phone-number.core.html#var-short-to-emergency.3F) | Checks if a phone numer can be used to connect to an emergency | 23 | 24 | 25 | ## Specs 26 | 27 | Clojure Spec is used in the phone-number library to validate data and generate 28 | property-based tests. Most of the defined specs have generators attached. 29 | 30 | There are 3 groups of specs: 31 | 32 | * **Input specs**, created for easy data validation. 33 | (ns-prefix: `phone-number.input`) 34 | 35 | * **Generic specs** used to describe the output data. 36 | (ns-prefix: `phone-number`) 37 | 38 | * Specs that are used **internally** to test the library for corner cases 39 | and make sure that new features or other changes won't break anything. 40 | (ns-prefixes: `phone-number.arg`, `phone-number.args`, `phone-number.props`) 41 | 42 | This page lists the input and some of the generic specs. To use them just require 43 | `phone-number.spec`, `clojure.spec.alpha` and optionally `clojure.spec.gen.alpha`: 44 | 45 | ``` clojure 46 | (require [phone-number.spec :as spec] 47 | [clojure.spec.alpha :as s] 48 | [clojure.spec.gen.alpha :as gen]) 49 | ``` 50 | 51 | | Spec Name | Data description | 52 | |-----------------------------------|-------------------------------------------------------| 53 | |`:phone-number.input/region` | region code | 54 | |`:phone-number.input/type` | phone number type | 55 | |`:phone-number.input/leniency` | phone number leniency | 56 | |`:phone-number.input/format` | phone number format | 57 | |`:phone-number.input/format-global` | phone number format
(with calling code prefix) | 58 | |`:phone-number.input/format-regional` | phone number format
(without calling code prefix) | 59 | |`:phone-number.input/tz-format` | time zone format | 60 | |`:phone-number.input/net-code` | global network calling code | 61 | |`:phone-number.input/country-code` | country calling code | 62 | |`:phone-number.input/calling-code` | calling code (either global or country) | 63 | |`:phone-number.input/cost` | cost class of short numbers | 64 | |`:phone-number.input/native` | phone number in native format
(`PhoneNumber` object)| 65 | |`:phone-number.input/native-valid` | native phone number which is valid | 66 | |`:phone-number.input/string` | phone number as a string | 67 | |`:phone-number.input/string-global` | phone number as a string with a calling code | 68 | |`:phone-number.input/string-regional` | phone number as a string without a calling code | 69 | |`:phone-number.input/string-valid` | valid phone number as a string | 70 | |`:phone-number.input/string-invalid` | invalid phone number as a string | 71 | |`:phone-number.input/numeric` | phone number as natural number without calling code | 72 | |`:phone-number/info` | phone number as a map | 73 | |`:phone-number/info-valid` | valid phone number as a map | 74 | |`:phone-number/info-invalid` | invalid phone number as a map | 75 | |`:phone-number.input/possible` | possible phone number | 76 | |`:phone-number.input/impossible` | impossible phone number | 77 | |`:phone-number.input/unknown` | phone number of unknown type | 78 | |`:phone-number.input/has-region` | phone number with region code information | 79 | |`:phone-number.input/has-calling-code` | phone number with calling code | 80 | |`:phone-number.input/has-location` | phone number having geographical location | 81 | |`:phone-number.input/has-time-zone` | phone number having time zone information | 82 | |`:phone-number.input/has-known-type` | phone number of known type | 83 | |`:phone-number.input/mobile` | mobile phone number | 84 | |`:phone-number.input/fixed-line` | fixed-line phone number | 85 | |`:phone-number.input/toll-free` | toll-free phone number | 86 | |`:phone-number.input/premium-rate` | premium-rate phone number | 87 | |`:phone-number.input/shared-cost` | shared-cost phone number | 88 | |`:phone-number.input/voip` | VoIP phone number | 89 | |`:phone-number.input/personal ` | personal phone number | 90 | |`:phone-number.input/pager` | pager number | 91 | |`:phone-number.input/uan` | UAN number | 92 | |`:phone-number.input/voicemail` | voicemail number | 93 | |`:phone-number.input/fixed-line-or-mobile`| fixed-line or mobile number (incl. uncertain) | 94 | |`:phone-number.input/uncertain-fixed-line-or-mobile` | uncertain number (fixed line or mobile) | 95 | |`:phone-number.input/maybe-mobile` | uncertain number (fixed line or mobile) or mobile | 96 | |`:phone-number.input/maybe-fixed-line` | uncertain number (fixed line or mobile) or fixed-line | 97 | |`:phone-number.input/short` | valid short number | 98 | |`:phone-number.input/maybe-short` | possible short number | 99 | |`:phone-number.input.short/valid` | valid short number | 100 | |`:phone-number.input.short/invalid` | invalid short number | 101 | |`:phone-number.input.short/possible` | possible short number | 102 | |`:phone-number.input.short/carrier-specific`| carrier-specific short number | 103 | |`:phone-number.input.short/info` | short number properties as a map | 104 | |`:phone-number.input/number` | phone number (with calling code or without) | 105 | 106 | Phone-number also contains specs for functions, however they are intended for testing 107 | and it is **NOT RECOMMENDED** to enable the **instrumentation** in production. 108 | 109 | Please note that if you intend to use phone-number's specs in a program (not in 110 | phone-number's REPL) you should add proper dependencies since production profile of 111 | phone-number does not depend on spec nor test library. Example, minimal `deps.edn`: 112 | 113 | ``` clojure 114 | {:paths ["src" "resources"] 115 | 116 | :deps {io.randomseed/phone-number {:mvn/version "8.12.16-1"}} 117 | 118 | :aliases { 119 | :dev { 120 | :extra-deps {org.clojure/spec.alpha {:mvn/version "0.2.194"} 121 | org.clojure/test.check {:mvn/version "1.1.0"}} 122 | :extra-paths ["dev/src" "test"] 123 | :jvm-opts ["-Dclojure.spec.compile-asserts=true"]} 124 | 125 | :test { 126 | :extra-paths ["test"] 127 | :extra-deps {org.clojure/test.check {:mvn/version "1.1.0"}}}} 128 | ``` 129 | -------------------------------------------------------------------------------- /doc/40_development.md: -------------------------------------------------------------------------------- 1 | # Development 2 | 3 | [![CircleCI](https://circleci.com/gh/randomseed-io/phone-number.svg?style=svg)](https://circleci.com/gh/randomseed-io/phone-number) 4 | 5 | ## Source code 6 | 7 | * https://github.com/randomseed-io/phone-number 8 | 9 | ## Common tasks 10 | 11 | ### Building docs 12 | 13 | ```bash 14 | make docs 15 | ``` 16 | 17 | ### Building JAR 18 | 19 | ```bash 20 | make jar 21 | ``` 22 | 23 | ### Rebuilding POM 24 | 25 | ```bash 26 | make pom 27 | ``` 28 | 29 | ### Signing POM 30 | 31 | ```bash 32 | make sig 33 | ``` 34 | 35 | ### Deploying to Clojars 36 | 37 | ```bash 38 | make deploy 39 | ``` 40 | 41 | ### Interactive development 42 | 43 | ```bash 44 | bin/repl 45 | ``` 46 | 47 | Starts REPL and nREPL server (port number is stored in `.nrepl-port`). 48 | 49 | ### Testing 50 | 51 | ```bash 52 | bin/test 53 | ``` 54 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | pom.xml 2 | pom.xml.asc 3 | *.jar 4 | *.class 5 | /lib/ 6 | /classes/ 7 | /target/ 8 | /checkouts/ 9 | .lein-deps-sum 10 | .lein-repl-history 11 | .lein-plugins/ 12 | .lein-failures 13 | .nrepl-port 14 | .cpcache/ 15 | -------------------------------------------------------------------------------- /docs/40_development.html: -------------------------------------------------------------------------------- 1 | 3 | Development

Development

4 |

CircleCI

5 |

Source code

6 | 9 |

Common tasks

10 |

Building docs

11 |
make docs
12 | 
13 |

Building JAR

14 |
make jar
15 | 
16 |

Rebuilding POM

17 |
make pom
18 | 
19 |

Signing POM

20 |
make sig
21 | 
22 |

Deploying to Clojars

23 |
make deploy
24 | 
25 |

Interactive development

26 |
bin/repl
27 | 
28 |

Starts REPL and nREPL server (port number is stored in .nrepl-port).

29 |

Testing

30 |
bin/test
31 | 
32 |
-------------------------------------------------------------------------------- /docs/LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /docs/css/default.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Helvetica, Arial, sans-serif; 3 | font-size: 15px; 4 | } 5 | 6 | pre, code { 7 | font-family: Monaco, DejaVu Sans Mono, Consolas, monospace; 8 | font-size: 9pt; 9 | margin: 15px 0; 10 | } 11 | 12 | h1 { 13 | font-weight: normal; 14 | font-size: 29px; 15 | margin: 10px 0 2px 0; 16 | padding: 0; 17 | } 18 | 19 | h2 { 20 | font-weight: normal; 21 | font-size: 25px; 22 | } 23 | 24 | h5.license { 25 | margin: 9px 0 22px 0; 26 | color: #555; 27 | font-weight: normal; 28 | font-size: 12px; 29 | font-style: italic; 30 | } 31 | 32 | .document h1, .namespace-index h1 { 33 | font-size: 32px; 34 | margin-top: 12px; 35 | } 36 | 37 | #header, #content, .sidebar { 38 | position: fixed; 39 | } 40 | 41 | #header { 42 | top: 0; 43 | left: 0; 44 | right: 0; 45 | height: 22px; 46 | color: #f5f5f5; 47 | padding: 5px 7px; 48 | } 49 | 50 | #content { 51 | top: 32px; 52 | right: 0; 53 | bottom: 0; 54 | overflow: auto; 55 | background: #fff; 56 | color: #333; 57 | padding: 0 18px; 58 | } 59 | 60 | .sidebar { 61 | position: fixed; 62 | top: 32px; 63 | bottom: 0; 64 | overflow: auto; 65 | } 66 | 67 | .sidebar.primary { 68 | background: #e2e2e2; 69 | border-right: solid 1px #cccccc; 70 | left: 0; 71 | width: 250px; 72 | } 73 | 74 | .sidebar.secondary { 75 | background: #f2f2f2; 76 | border-right: solid 1px #d7d7d7; 77 | left: 251px; 78 | width: 200px; 79 | } 80 | 81 | #content.namespace-index, #content.document { 82 | left: 251px; 83 | } 84 | 85 | #content.namespace-docs { 86 | left: 452px; 87 | } 88 | 89 | #content.document { 90 | padding-bottom: 10%; 91 | } 92 | 93 | #header { 94 | background: #3f3f3f; 95 | box-shadow: 0 0 8px rgba(0, 0, 0, 0.4); 96 | z-index: 100; 97 | } 98 | 99 | #header h1 { 100 | margin: 0; 101 | padding: 0; 102 | font-size: 18px; 103 | font-weight: lighter; 104 | text-shadow: -1px -1px 0px #333; 105 | } 106 | 107 | #header h1 .project-version { 108 | font-weight: normal; 109 | } 110 | 111 | .project-version { 112 | padding-left: 0.15em; 113 | } 114 | 115 | #header a, .sidebar a { 116 | display: block; 117 | text-decoration: none; 118 | } 119 | 120 | #header a { 121 | color: #f5f5f5; 122 | } 123 | 124 | .sidebar a { 125 | color: #333; 126 | } 127 | 128 | #header h2 { 129 | float: right; 130 | font-size: 9pt; 131 | font-weight: normal; 132 | margin: 4px 3px; 133 | padding: 0; 134 | color: #bbb; 135 | } 136 | 137 | #header h2 a { 138 | display: inline; 139 | } 140 | 141 | .sidebar h3 { 142 | margin: 0; 143 | padding: 10px 13px 0 13px; 144 | font-size: 19px; 145 | font-weight: lighter; 146 | } 147 | 148 | .sidebar h3 a { 149 | color: #444; 150 | } 151 | 152 | .sidebar h3.no-link { 153 | color: #636363; 154 | } 155 | 156 | .sidebar ul { 157 | padding: 7px 0 6px 0; 158 | margin: 0; 159 | } 160 | 161 | .sidebar ul.index-link { 162 | padding-bottom: 4px; 163 | } 164 | 165 | .sidebar li { 166 | display: block; 167 | vertical-align: middle; 168 | } 169 | 170 | .sidebar li a, .sidebar li .no-link { 171 | border-left: 3px solid transparent; 172 | padding: 0 10px; 173 | white-space: nowrap; 174 | } 175 | 176 | .sidebar li .no-link { 177 | display: block; 178 | color: #777; 179 | font-style: italic; 180 | } 181 | 182 | .sidebar li .inner { 183 | display: inline-block; 184 | padding-top: 7px; 185 | height: 24px; 186 | } 187 | 188 | .sidebar li a, .sidebar li .tree { 189 | height: 31px; 190 | } 191 | 192 | .depth-1 .inner { padding-left: 2px; } 193 | .depth-2 .inner { padding-left: 6px; } 194 | .depth-3 .inner { padding-left: 20px; } 195 | .depth-4 .inner { padding-left: 34px; } 196 | .depth-5 .inner { padding-left: 48px; } 197 | .depth-6 .inner { padding-left: 62px; } 198 | 199 | .sidebar li .tree { 200 | display: block; 201 | float: left; 202 | position: relative; 203 | top: -10px; 204 | margin: 0 4px 0 0; 205 | padding: 0; 206 | } 207 | 208 | .sidebar li.depth-1 .tree { 209 | display: none; 210 | } 211 | 212 | .sidebar li .tree .top, .sidebar li .tree .bottom { 213 | display: block; 214 | margin: 0; 215 | padding: 0; 216 | width: 7px; 217 | } 218 | 219 | .sidebar li .tree .top { 220 | border-left: 1px solid #aaa; 221 | border-bottom: 1px solid #aaa; 222 | height: 19px; 223 | } 224 | 225 | .sidebar li .tree .bottom { 226 | height: 22px; 227 | } 228 | 229 | .sidebar li.branch .tree .bottom { 230 | border-left: 1px solid #aaa; 231 | } 232 | 233 | .sidebar.primary li.current a { 234 | border-left: 3px solid #a33; 235 | color: #a33; 236 | } 237 | 238 | .sidebar.secondary li.current a { 239 | border-left: 3px solid #33a; 240 | color: #33a; 241 | } 242 | 243 | .namespace-index h2 { 244 | margin: 30px 0 0 0; 245 | } 246 | 247 | .namespace-index h3 { 248 | font-size: 16px; 249 | font-weight: bold; 250 | margin-bottom: 0; 251 | } 252 | 253 | .namespace-index .topics { 254 | padding-left: 30px; 255 | margin: 11px 0 0 0; 256 | } 257 | 258 | .namespace-index .topics li { 259 | padding: 5px 0; 260 | } 261 | 262 | .namespace-docs h3 { 263 | font-size: 18px; 264 | font-weight: bold; 265 | } 266 | 267 | .public h3 { 268 | margin: 0; 269 | float: left; 270 | } 271 | 272 | .usage { 273 | clear: both; 274 | } 275 | 276 | .public { 277 | margin: 0; 278 | border-top: 1px solid #e0e0e0; 279 | padding-top: 14px; 280 | padding-bottom: 6px; 281 | } 282 | 283 | .public:last-child { 284 | margin-bottom: 20%; 285 | } 286 | 287 | .members .public:last-child { 288 | margin-bottom: 0; 289 | } 290 | 291 | .members { 292 | margin: 15px 0; 293 | } 294 | 295 | .members h4 { 296 | color: #555; 297 | font-weight: normal; 298 | font-variant: small-caps; 299 | margin: 0 0 5px 0; 300 | } 301 | 302 | .members .inner { 303 | padding-top: 5px; 304 | padding-left: 12px; 305 | margin-top: 2px; 306 | margin-left: 7px; 307 | border-left: 1px solid #bbb; 308 | } 309 | 310 | #content .members .inner h3 { 311 | font-size: 12pt; 312 | } 313 | 314 | .members .public { 315 | border-top: none; 316 | margin-top: 0; 317 | padding-top: 6px; 318 | padding-bottom: 0; 319 | } 320 | 321 | .members .public:first-child { 322 | padding-top: 0; 323 | } 324 | 325 | h4.type, 326 | h4.dynamic, 327 | h4.added, 328 | h4.deprecated { 329 | float: left; 330 | margin: 3px 10px 15px 0; 331 | font-size: 15px; 332 | font-weight: bold; 333 | font-variant: small-caps; 334 | } 335 | 336 | .public h4.type, 337 | .public h4.dynamic, 338 | .public h4.added, 339 | .public h4.deprecated { 340 | font-size: 13px; 341 | font-weight: bold; 342 | margin: 3px 0 0 10px; 343 | } 344 | 345 | .members h4.type, 346 | .members h4.added, 347 | .members h4.deprecated { 348 | margin-top: 1px; 349 | } 350 | 351 | h4.type { 352 | color: #717171; 353 | } 354 | 355 | h4.dynamic { 356 | color: #9933aa; 357 | } 358 | 359 | h4.added { 360 | color: #508820; 361 | } 362 | 363 | h4.deprecated { 364 | color: #880000; 365 | } 366 | 367 | .namespace { 368 | margin-bottom: 30px; 369 | } 370 | 371 | .namespace:last-child { 372 | margin-bottom: 10%; 373 | } 374 | 375 | .index { 376 | padding: 0; 377 | font-size: 80%; 378 | margin: 15px 0; 379 | line-height: 16px; 380 | } 381 | 382 | .index * { 383 | display: inline; 384 | } 385 | 386 | .index p { 387 | padding-right: 3px; 388 | } 389 | 390 | .index li { 391 | padding-right: 5px; 392 | } 393 | 394 | .index ul { 395 | padding-left: 0; 396 | } 397 | 398 | .type-sig { 399 | clear: both; 400 | color: #088; 401 | } 402 | 403 | .type-sig pre { 404 | padding-top: 10px; 405 | margin: 0; 406 | } 407 | 408 | .usage code { 409 | display: block; 410 | color: #008; 411 | margin: 2px 0; 412 | } 413 | 414 | .usage code:first-child { 415 | padding-top: 10px; 416 | } 417 | 418 | p { 419 | margin: 15px 0; 420 | } 421 | 422 | .public p:first-child, .public pre.plaintext { 423 | margin-top: 12px; 424 | } 425 | 426 | .doc { 427 | margin: 0 0 26px 0; 428 | clear: both; 429 | } 430 | 431 | .public .doc { 432 | margin: 0; 433 | } 434 | 435 | .namespace-index .doc { 436 | margin-bottom: 20px; 437 | } 438 | 439 | .namespace-index .namespace .doc { 440 | margin-bottom: 10px; 441 | } 442 | 443 | .markdown p, .markdown li, .markdown dt, .markdown dd, .markdown td { 444 | line-height: 22px; 445 | } 446 | 447 | .markdown li { 448 | padding: 2px 0; 449 | } 450 | 451 | .markdown h2 { 452 | font-weight: normal; 453 | font-size: 25px; 454 | margin: 30px 0 10px 0; 455 | } 456 | 457 | .markdown h3 { 458 | font-weight: normal; 459 | font-size: 20px; 460 | margin: 30px 0 0 0; 461 | } 462 | 463 | .markdown h4 { 464 | font-size: 15px; 465 | margin: 22px 0 -4px 0; 466 | } 467 | 468 | .doc, .public, .namespace .index { 469 | max-width: 680px; 470 | overflow-x: visible; 471 | } 472 | 473 | .markdown pre > code { 474 | display: block; 475 | padding: 10px; 476 | } 477 | 478 | .markdown pre > code, .src-link a { 479 | border: 1px solid #e4e4e4; 480 | border-radius: 2px; 481 | } 482 | 483 | .markdown code:not(.hljs), .src-link a { 484 | background: #f6f6f6; 485 | } 486 | 487 | pre.deps { 488 | display: inline-block; 489 | margin: 0 10px; 490 | border: 1px solid #e4e4e4; 491 | border-radius: 2px; 492 | padding: 10px; 493 | background-color: #f6f6f6; 494 | } 495 | 496 | .markdown hr { 497 | border-style: solid; 498 | border-top: none; 499 | color: #ccc; 500 | } 501 | 502 | .doc ul, .doc ol { 503 | padding-left: 30px; 504 | } 505 | 506 | .doc table { 507 | border-collapse: collapse; 508 | margin: 0 10px; 509 | } 510 | 511 | .doc table td, .doc table th { 512 | border: 1px solid #dddddd; 513 | padding: 4px 6px; 514 | } 515 | 516 | .doc table th { 517 | background: #f2f2f2; 518 | } 519 | 520 | .doc dl { 521 | margin: 0 10px 20px 10px; 522 | } 523 | 524 | .doc dl dt { 525 | font-weight: bold; 526 | margin: 0; 527 | padding: 3px 0; 528 | border-bottom: 1px solid #ddd; 529 | } 530 | 531 | .doc dl dd { 532 | padding: 5px 0; 533 | margin: 0 0 5px 10px; 534 | } 535 | 536 | .doc abbr { 537 | border-bottom: 1px dotted #333; 538 | font-variant: none; 539 | cursor: help; 540 | } 541 | 542 | .src-link { 543 | margin-bottom: 15px; 544 | } 545 | 546 | .src-link a { 547 | font-size: 70%; 548 | padding: 1px 4px; 549 | text-decoration: none; 550 | color: #5555bb; 551 | } 552 | -------------------------------------------------------------------------------- /docs/css/highlight.css: -------------------------------------------------------------------------------- 1 | /* 2 | github.com style (c) Vasily Polovnyov 3 | */ 4 | 5 | .hljs { 6 | display: block; 7 | overflow-x: auto; 8 | padding: 0.5em; 9 | color: #333; 10 | background: #f8f8f8; 11 | } 12 | 13 | .hljs-comment, 14 | .hljs-quote { 15 | color: #998; 16 | font-style: italic; 17 | } 18 | 19 | .hljs-keyword, 20 | .hljs-selector-tag, 21 | .hljs-subst { 22 | color: #333; 23 | font-weight: bold; 24 | } 25 | 26 | .hljs-number, 27 | .hljs-literal, 28 | .hljs-variable, 29 | .hljs-template-variable, 30 | .hljs-tag .hljs-attr { 31 | color: #008080; 32 | } 33 | 34 | .hljs-string, 35 | .hljs-doctag { 36 | color: #d14; 37 | } 38 | 39 | .hljs-title, 40 | .hljs-section, 41 | .hljs-selector-id { 42 | color: #900; 43 | font-weight: bold; 44 | } 45 | 46 | .hljs-subst { 47 | font-weight: normal; 48 | } 49 | 50 | .hljs-type, 51 | .hljs-class .hljs-title { 52 | color: #458; 53 | font-weight: bold; 54 | } 55 | 56 | .hljs-tag, 57 | .hljs-name, 58 | .hljs-attribute { 59 | color: #000080; 60 | font-weight: normal; 61 | } 62 | 63 | .hljs-regexp, 64 | .hljs-link { 65 | color: #009926; 66 | } 67 | 68 | .hljs-symbol, 69 | .hljs-bullet { 70 | color: #990073; 71 | } 72 | 73 | .hljs-built_in, 74 | .hljs-builtin-name { 75 | color: #0086b3; 76 | } 77 | 78 | .hljs-meta { 79 | color: #999; 80 | font-weight: bold; 81 | } 82 | 83 | .hljs-deletion { 84 | background: #fdd; 85 | } 86 | 87 | .hljs-addition { 88 | background: #dfd; 89 | } 90 | 91 | .hljs-emphasis { 92 | font-style: italic; 93 | } 94 | 95 | .hljs-strong { 96 | font-weight: bold; 97 | } 98 | -------------------------------------------------------------------------------- /docs/css/randomseed.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Open+Sans&display=swap'); 2 | 3 | body { 4 | font-family: 'Open Sans', 'Helvetica Neue', 'PT Sans', Helvetica, sans-serif; 5 | font-size: 15.5px; 6 | } 7 | 8 | pre, code { 9 | font-size: 10pt; 10 | } 11 | 12 | .sidebar.primary { 13 | background: #e2e2e2; 14 | border-right: solid 1px #cccccc; 15 | } 16 | 17 | .sidebar.primary li.current a { 18 | border-left: 3px solid #a33; 19 | color: #a33; 20 | } 21 | 22 | .sidebar a { 23 | color: #333; 24 | } 25 | 26 | .sidebar h3.no-link { 27 | color: #636363; 28 | } 29 | -------------------------------------------------------------------------------- /docs/js/highlight.min.js: -------------------------------------------------------------------------------- 1 | /*! highlight.js v9.6.0 | BSD3 License | git.io/hljslicense */ 2 | !function(e){var n="object"==typeof window&&window||"object"==typeof self&&self;"undefined"!=typeof exports?e(exports):n&&(n.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return n.hljs}))}(function(e){function n(e){return e.replace(/[&<>]/gm,function(e){return I[e]})}function t(e){return e.nodeName.toLowerCase()}function r(e,n){var t=e&&e.exec(n);return t&&0===t.index}function a(e){return k.test(e)}function i(e){var n,t,r,i,o=e.className+" ";if(o+=e.parentNode?e.parentNode.className:"",t=B.exec(o))return R(t[1])?t[1]:"no-highlight";for(o=o.split(/\s+/),n=0,r=o.length;r>n;n++)if(i=o[n],a(i)||R(i))return i}function o(e,n){var t,r={};for(t in e)r[t]=e[t];if(n)for(t in n)r[t]=n[t];return r}function u(e){var n=[];return function r(e,a){for(var i=e.firstChild;i;i=i.nextSibling)3===i.nodeType?a+=i.nodeValue.length:1===i.nodeType&&(n.push({event:"start",offset:a,node:i}),a=r(i,a),t(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:i}));return a}(e,0),n}function c(e,r,a){function i(){return e.length&&r.length?e[0].offset!==r[0].offset?e[0].offset"}function u(e){l+=""}function c(e){("start"===e.event?o:u)(e.node)}for(var s=0,l="",f=[];e.length||r.length;){var g=i();if(l+=n(a.substr(s,g[0].offset-s)),s=g[0].offset,g===e){f.reverse().forEach(u);do c(g.splice(0,1)[0]),g=i();while(g===e&&g.length&&g[0].offset===s);f.reverse().forEach(o)}else"start"===g[0].event?f.push(g[0].node):f.pop(),c(g.splice(0,1)[0])}return l+n(a.substr(s))}function s(e){function n(e){return e&&e.source||e}function t(t,r){return new RegExp(n(t),"m"+(e.cI?"i":"")+(r?"g":""))}function r(a,i){if(!a.compiled){if(a.compiled=!0,a.k=a.k||a.bK,a.k){var u={},c=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(" ").forEach(function(e){var t=e.split("|");u[t[0]]=[n,t[1]?Number(t[1]):1]})};"string"==typeof a.k?c("keyword",a.k):E(a.k).forEach(function(e){c(e,a.k[e])}),a.k=u}a.lR=t(a.l||/\w+/,!0),i&&(a.bK&&(a.b="\\b("+a.bK.split(" ").join("|")+")\\b"),a.b||(a.b=/\B|\b/),a.bR=t(a.b),a.e||a.eW||(a.e=/\B|\b/),a.e&&(a.eR=t(a.e)),a.tE=n(a.e)||"",a.eW&&i.tE&&(a.tE+=(a.e?"|":"")+i.tE)),a.i&&(a.iR=t(a.i)),null==a.r&&(a.r=1),a.c||(a.c=[]);var s=[];a.c.forEach(function(e){e.v?e.v.forEach(function(n){s.push(o(e,n))}):s.push("self"===e?a:e)}),a.c=s,a.c.forEach(function(e){r(e,a)}),a.starts&&r(a.starts,i);var l=a.c.map(function(e){return e.bK?"\\.?("+e.b+")\\.?":e.b}).concat([a.tE,a.i]).map(n).filter(Boolean);a.t=l.length?t(l.join("|"),!0):{exec:function(){return null}}}}r(e)}function l(e,t,a,i){function o(e,n){var t,a;for(t=0,a=n.c.length;a>t;t++)if(r(n.c[t].bR,e))return n.c[t]}function u(e,n){if(r(e.eR,n)){for(;e.endsParent&&e.parent;)e=e.parent;return e}return e.eW?u(e.parent,n):void 0}function c(e,n){return!a&&r(n.iR,e)}function g(e,n){var t=N.cI?n[0].toLowerCase():n[0];return e.k.hasOwnProperty(t)&&e.k[t]}function h(e,n,t,r){var a=r?"":y.classPrefix,i='',i+n+o}function p(){var e,t,r,a;if(!E.k)return n(B);for(a="",t=0,E.lR.lastIndex=0,r=E.lR.exec(B);r;)a+=n(B.substr(t,r.index-t)),e=g(E,r),e?(M+=e[1],a+=h(e[0],n(r[0]))):a+=n(r[0]),t=E.lR.lastIndex,r=E.lR.exec(B);return a+n(B.substr(t))}function d(){var e="string"==typeof E.sL;if(e&&!x[E.sL])return n(B);var t=e?l(E.sL,B,!0,L[E.sL]):f(B,E.sL.length?E.sL:void 0);return E.r>0&&(M+=t.r),e&&(L[E.sL]=t.top),h(t.language,t.value,!1,!0)}function b(){k+=null!=E.sL?d():p(),B=""}function v(e){k+=e.cN?h(e.cN,"",!0):"",E=Object.create(e,{parent:{value:E}})}function m(e,n){if(B+=e,null==n)return b(),0;var t=o(n,E);if(t)return t.skip?B+=n:(t.eB&&(B+=n),b(),t.rB||t.eB||(B=n)),v(t,n),t.rB?0:n.length;var r=u(E,n);if(r){var a=E;a.skip?B+=n:(a.rE||a.eE||(B+=n),b(),a.eE&&(B=n));do E.cN&&(k+=C),E.skip||(M+=E.r),E=E.parent;while(E!==r.parent);return r.starts&&v(r.starts,""),a.rE?0:n.length}if(c(n,E))throw new Error('Illegal lexeme "'+n+'" for mode "'+(E.cN||"")+'"');return B+=n,n.length||1}var N=R(e);if(!N)throw new Error('Unknown language: "'+e+'"');s(N);var w,E=i||N,L={},k="";for(w=E;w!==N;w=w.parent)w.cN&&(k=h(w.cN,"",!0)+k);var B="",M=0;try{for(var I,j,O=0;;){if(E.t.lastIndex=O,I=E.t.exec(t),!I)break;j=m(t.substr(O,I.index-O),I[0]),O=I.index+j}for(m(t.substr(O)),w=E;w.parent;w=w.parent)w.cN&&(k+=C);return{r:M,value:k,language:e,top:E}}catch(T){if(T.message&&-1!==T.message.indexOf("Illegal"))return{r:0,value:n(t)};throw T}}function f(e,t){t=t||y.languages||E(x);var r={r:0,value:n(e)},a=r;return t.filter(R).forEach(function(n){var t=l(n,e,!1);t.language=n,t.r>a.r&&(a=t),t.r>r.r&&(a=r,r=t)}),a.language&&(r.second_best=a),r}function g(e){return y.tabReplace||y.useBR?e.replace(M,function(e,n){return y.useBR&&"\n"===e?"
":y.tabReplace?n.replace(/\t/g,y.tabReplace):void 0}):e}function h(e,n,t){var r=n?L[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),-1===e.indexOf(r)&&a.push(r),a.join(" ").trim()}function p(e){var n,t,r,o,s,p=i(e);a(p)||(y.useBR?(n=document.createElementNS("http://www.w3.org/1999/xhtml","div"),n.innerHTML=e.innerHTML.replace(/\n/g,"").replace(//g,"\n")):n=e,s=n.textContent,r=p?l(p,s,!0):f(s),t=u(n),t.length&&(o=document.createElementNS("http://www.w3.org/1999/xhtml","div"),o.innerHTML=r.value,r.value=c(t,u(o),s)),r.value=g(r.value),e.innerHTML=r.value,e.className=h(e.className,p,r.language),e.result={language:r.language,re:r.r},r.second_best&&(e.second_best={language:r.second_best.language,re:r.second_best.r}))}function d(e){y=o(y,e)}function b(){if(!b.called){b.called=!0;var e=document.querySelectorAll("pre code");w.forEach.call(e,p)}}function v(){addEventListener("DOMContentLoaded",b,!1),addEventListener("load",b,!1)}function m(n,t){var r=x[n]=t(e);r.aliases&&r.aliases.forEach(function(e){L[e]=n})}function N(){return E(x)}function R(e){return e=(e||"").toLowerCase(),x[e]||x[L[e]]}var w=[],E=Object.keys,x={},L={},k=/^(no-?highlight|plain|text)$/i,B=/\blang(?:uage)?-([\w-]+)\b/i,M=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,C="
",y={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0},I={"&":"&","<":"<",">":">"};return e.highlight=l,e.highlightAuto=f,e.fixMarkup=g,e.highlightBlock=p,e.configure=d,e.initHighlighting=b,e.initHighlightingOnLoad=v,e.registerLanguage=m,e.listLanguages=N,e.getLanguage=R,e.inherit=o,e.IR="[a-zA-Z]\\w*",e.UIR="[a-zA-Z_]\\w*",e.NR="\\b\\d+(\\.\\d+)?",e.CNR="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BNR="\\b(0b[01]+)",e.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BE={b:"\\\\[\\s\\S]",r:0},e.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[e.BE]},e.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[e.BE]},e.PWM={b:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|like)\b/},e.C=function(n,t,r){var a=e.inherit({cN:"comment",b:n,e:t,c:[]},r||{});return a.c.push(e.PWM),a.c.push({cN:"doctag",b:"(?:TODO|FIXME|NOTE|BUG|XXX):",r:0}),a},e.CLCM=e.C("//","$"),e.CBCM=e.C("/\\*","\\*/"),e.HCM=e.C("#","$"),e.NM={cN:"number",b:e.NR,r:0},e.CNM={cN:"number",b:e.CNR,r:0},e.BNM={cN:"number",b:e.BNR,r:0},e.CSSNM={cN:"number",b:e.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},e.RM={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[e.BE,{b:/\[/,e:/\]/,r:0,c:[e.BE]}]},e.TM={cN:"title",b:e.IR,r:0},e.UTM={cN:"title",b:e.UIR,r:0},e.METHOD_GUARD={b:"\\.\\s*"+e.UIR,r:0},e});hljs.registerLanguage("clojure",function(e){var t={"builtin-name":"def defonce cond apply if-not if-let if not not= = < > <= >= == + / * - rem quot neg? pos? delay? symbol? keyword? true? false? integer? empty? coll? list? set? ifn? fn? associative? sequential? sorted? counted? reversible? number? decimal? class? distinct? isa? float? rational? reduced? ratio? odd? even? char? seq? vector? string? map? nil? contains? zero? instance? not-every? not-any? libspec? -> ->> .. . inc compare do dotimes mapcat take remove take-while drop letfn drop-last take-last drop-while while intern condp case reduced cycle split-at split-with repeat replicate iterate range merge zipmap declare line-seq sort comparator sort-by dorun doall nthnext nthrest partition eval doseq await await-for let agent atom send send-off release-pending-sends add-watch mapv filterv remove-watch agent-error restart-agent set-error-handler error-handler set-error-mode! error-mode shutdown-agents quote var fn loop recur throw try monitor-enter monitor-exit defmacro defn defn- macroexpand macroexpand-1 for dosync and or when when-not when-let comp juxt partial sequence memoize constantly complement identity assert peek pop doto proxy defstruct first rest cons defprotocol cast coll deftype defrecord last butlast sigs reify second ffirst fnext nfirst nnext defmulti defmethod meta with-meta ns in-ns create-ns import refer keys select-keys vals key val rseq name namespace promise into transient persistent! conj! assoc! dissoc! pop! disj! use class type num float double short byte boolean bigint biginteger bigdec print-method print-dup throw-if printf format load compile get-in update-in pr pr-on newline flush read slurp read-line subvec with-open memfn time re-find re-groups rand-int rand mod locking assert-valid-fdecl alias resolve ref deref refset swap! reset! set-validator! compare-and-set! alter-meta! reset-meta! commute get-validator alter ref-set ref-history-count ref-min-history ref-max-history ensure sync io! new next conj set! to-array future future-call into-array aset gen-class reduce map filter find empty hash-map hash-set sorted-map sorted-map-by sorted-set sorted-set-by vec vector seq flatten reverse assoc dissoc list disj get union difference intersection extend extend-type extend-protocol int nth delay count concat chunk chunk-buffer chunk-append chunk-first chunk-rest max min dec unchecked-inc-int unchecked-inc unchecked-dec-inc unchecked-dec unchecked-negate unchecked-add-int unchecked-add unchecked-subtract-int unchecked-subtract chunk-next chunk-cons chunked-seq? prn vary-meta lazy-seq spread list* str find-keyword keyword symbol gensym force rationalize"},r="a-zA-Z_\\-!.?+*=<>&#'",n="["+r+"]["+r+"0-9/;:]*",a="[-+]?\\d+(\\.\\d+)?",o={b:n,r:0},s={cN:"number",b:a,r:0},i=e.inherit(e.QSM,{i:null}),c=e.C(";","$",{r:0}),d={cN:"literal",b:/\b(true|false|nil)\b/},l={b:"[\\[\\{]",e:"[\\]\\}]"},m={cN:"comment",b:"\\^"+n},p=e.C("\\^\\{","\\}"),u={cN:"symbol",b:"[:]{1,2}"+n},f={b:"\\(",e:"\\)"},h={eW:!0,r:0},y={k:t,l:n,cN:"name",b:n,starts:h},b=[f,i,m,p,c,u,l,s,d,o];return f.c=[e.C("comment",""),y,h],h.c=b,l.c=b,{aliases:["clj"],i:/\S/,c:[f,i,m,p,c,u,l,s,d]}});hljs.registerLanguage("clojure-repl",function(e){return{c:[{cN:"meta",b:/^([\w.-]+|\s*#_)=>/,starts:{e:/$/,sL:"clojure"}}]}}); -------------------------------------------------------------------------------- /docs/js/page_effects.js: -------------------------------------------------------------------------------- 1 | function visibleInParent(element) { 2 | var position = $(element).position().top 3 | return position > -50 && position < ($(element).offsetParent().height() - 50) 4 | } 5 | 6 | function hasFragment(link, fragment) { 7 | return $(link).attr("href").indexOf("#" + fragment) != -1 8 | } 9 | 10 | function findLinkByFragment(elements, fragment) { 11 | return $(elements).filter(function(i, e) { return hasFragment(e, fragment)}).first() 12 | } 13 | 14 | function scrollToCurrentVarLink(elements) { 15 | var elements = $(elements); 16 | var parent = elements.offsetParent(); 17 | 18 | if (elements.length == 0) return; 19 | 20 | var top = elements.first().position().top; 21 | var bottom = elements.last().position().top + elements.last().height(); 22 | 23 | if (top >= 0 && bottom <= parent.height()) return; 24 | 25 | if (top < 0) { 26 | parent.scrollTop(parent.scrollTop() + top); 27 | } 28 | else if (bottom > parent.height()) { 29 | parent.scrollTop(parent.scrollTop() + bottom - parent.height()); 30 | } 31 | } 32 | 33 | function setCurrentVarLink() { 34 | $('.secondary a').parent().removeClass('current') 35 | $('.anchor'). 36 | filter(function(index) { return visibleInParent(this) }). 37 | each(function(index, element) { 38 | findLinkByFragment(".secondary a", element.id). 39 | parent(). 40 | addClass('current') 41 | }); 42 | scrollToCurrentVarLink('.secondary .current'); 43 | } 44 | 45 | var hasStorage = (function() { try { return localStorage.getItem } catch(e) {} }()) 46 | 47 | function scrollPositionId(element) { 48 | var directory = window.location.href.replace(/[^\/]+\.html$/, '') 49 | return 'scroll::' + $(element).attr('id') + '::' + directory 50 | } 51 | 52 | function storeScrollPosition(element) { 53 | if (!hasStorage) return; 54 | localStorage.setItem(scrollPositionId(element) + "::x", $(element).scrollLeft()) 55 | localStorage.setItem(scrollPositionId(element) + "::y", $(element).scrollTop()) 56 | } 57 | 58 | function recallScrollPosition(element) { 59 | if (!hasStorage) return; 60 | $(element).scrollLeft(localStorage.getItem(scrollPositionId(element) + "::x")) 61 | $(element).scrollTop(localStorage.getItem(scrollPositionId(element) + "::y")) 62 | } 63 | 64 | function persistScrollPosition(element) { 65 | recallScrollPosition(element) 66 | $(element).scroll(function() { storeScrollPosition(element) }) 67 | } 68 | 69 | function sidebarContentWidth(element) { 70 | var widths = $(element).find('.inner').map(function() { return $(this).innerWidth() }) 71 | return Math.max.apply(Math, widths) 72 | } 73 | 74 | function calculateSize(width, snap, margin, minimum) { 75 | if (width == 0) { 76 | return 0 77 | } 78 | else { 79 | return Math.max(minimum, (Math.ceil(width / snap) * snap) + (margin * 2)) 80 | } 81 | } 82 | 83 | function resizeSidebars() { 84 | var primaryWidth = sidebarContentWidth('.primary') 85 | var secondaryWidth = 0 86 | 87 | if ($('.secondary').length != 0) { 88 | secondaryWidth = sidebarContentWidth('.secondary') 89 | } 90 | 91 | // snap to grid 92 | primaryWidth = calculateSize(primaryWidth, 32, 13, 160) 93 | secondaryWidth = calculateSize(secondaryWidth, 32, 13, 160) 94 | 95 | $('.primary').css('width', primaryWidth) 96 | $('.secondary').css('width', secondaryWidth).css('left', primaryWidth + 1) 97 | 98 | if (secondaryWidth > 0) { 99 | $('#content').css('left', primaryWidth + secondaryWidth + 2) 100 | } 101 | else { 102 | $('#content').css('left', primaryWidth + 1) 103 | } 104 | } 105 | 106 | $(window).ready(resizeSidebars) 107 | $(window).ready(setCurrentVarLink) 108 | $(window).ready(function() { persistScrollPosition('.primary')}) 109 | $(window).ready(function() { 110 | $('#content').scroll(setCurrentVarLink) 111 | $(window).resize(setCurrentVarLink) 112 | }) 113 | -------------------------------------------------------------------------------- /docs/phone-number.calling-code.html: -------------------------------------------------------------------------------- 1 | 3 | phone-number.calling-code documentation

phone-number.calling-code

added in 8.12.4-0

Calling codes handling for phone-number.

4 |

all

added in 8.12.4-0

Set of supported calling codes.

5 |

all-arg

added in 8.12.16-1

Set of supported calling codes to be passed as arguments.

6 |

all-arg-vec

added in 8.12.16-1

Vector of all supported calling codes to be used as arguments.

7 |

all-vec

added in 8.12.4-0

Vector of all supported calling codes.

8 |

by-val

added in 8.12.4-0

Set of supported calling codes (values).

9 |

by-val-arg

added in 8.12.16-1

Set of supported calling codes (values) to be passed as arguments.

10 |

by-val-arg-vec

added in 8.12.16-1

Vector of all supported calling codes.

11 |

by-val-vec

added in 8.12.4-0

Vector of all supported calling codes.

12 |

generate-arg-sample

added in 8.12.16-1

(generate-arg-sample)(generate-arg-sample rng)

Generates random calling code.

13 |

generate-arg-sample-val

added in 8.12.16-1

(generate-arg-sample-val)(generate-arg-sample-val rng)

Generates random calling code.

14 |

generate-sample

added in 8.12.4-0

(generate-sample)(generate-sample rng)

Generates a random calling code.

15 |

generate-sample-val

added in 8.12.16-1

(generate-sample-val)(generate-sample-val rng)

Generates a random calling code.

16 |

parse

added in 8.12.4-0

(parse calling-code)

Parses a calling code and returns a value that can be supplied to Libphonenumber methods.

17 |

valid-arg?

added in 8.12.16-1

(valid-arg? calling-code)

Returns true if the given region-specification is a valid region code to be used as an argument, false otherwise.

18 |

valid?

added in 8.12.4-0

(valid? calling-code)

Returns true if the given region-specification is a valid region code, false otherwise.

19 |
-------------------------------------------------------------------------------- /docs/phone-number.country-code.html: -------------------------------------------------------------------------------- 1 | 3 | phone-number.country-code documentation

phone-number.country-code

added in 8.12.4-0

Country calling codes handling for phone-number.

4 |

all

added in 8.12.4-0

Set of supported country codes.

5 |

all-arg

added in 8.12.4-0

Set of supported country codes (to be used as arguments).

6 |

all-arg-vec

added in 8.12.16-1

Vector of all supported country codes (valid as args).

7 |

all-vec

added in 8.12.4-0

Vector of all supported country codes.

8 |

by-val

added in 8.12.4-0

Set of supported values of country codes.

9 |

by-val-arg

added in 8.12.4-0

Set of supported values of country codes (to be used as method arguments).

10 |

by-val-arg-vec

added in 8.12.16-1

Vector of all supported country codes (valid as args).

11 |

by-val-vec

added in 8.12.4-0

Vector of all supported country codes.

12 |

generate-arg-sample

added in 8.12.16-1

(generate-arg-sample)(generate-arg-sample rng)

Generates a random country calling code.

13 |

generate-arg-sample-val

added in 8.12.16-1

(generate-arg-sample-val)(generate-arg-sample-val rng)

Generates a random country calling code.

14 |

generate-sample

added in 8.12.4-0

(generate-sample)(generate-sample rng)

Generates a random country calling code.

15 |

generate-sample-val

added in 8.12.16-1

(generate-sample-val)(generate-sample-val rng)

Generates a random country calling code.

16 |

parse

added in 8.12.4-0

(parse calling-code)

Parses a country calling code and returns a value that can be supplied to Libphonenumber methods.

17 |

valid-arg?

added in 8.12.16-1

(valid-arg? calling-code)

Returns true if the given region-specification is a valid region code (to be used as an argument), false otherwise.

18 |

valid?

added in 8.12.4-0

(valid? calling-code)

Returns true if the given region-specification is a valid region code, false otherwise.

19 |
-------------------------------------------------------------------------------- /docs/phone-number.html: -------------------------------------------------------------------------------- 1 | 3 | phone-number documentation

phone-number

added in 8.12.4-2

Clojure interface to Libphonenumber.

4 |
-------------------------------------------------------------------------------- /docs/phone-number.match.html: -------------------------------------------------------------------------------- 1 | 3 | phone-number.match documentation

phone-number.match

added in 8.12.4-0

Match types for phone-number

4 |

all

added in 8.12.4-0

Map of phone number matches (keywords) to MatchType values.

5 |

all-arg

added in 8.12.16-1

Map of phone number matches (keywords) to MatchType values to be used as arguments.

6 |

by-val

added in 8.12.4-0

Map of MatchType values to phone number matches (keywords).

7 |

by-val-arg

added in 8.12.16-1

Map of MatchType values to phone number matches (keywords) to be used as arguments.

8 |

mapper

added in 8.12.4-0

(mapper m)

Generates a map from PhoneNumberMatch object.

9 |

none

added in 8.12.16-1

none-val

added in 8.12.16-1

-------------------------------------------------------------------------------- /docs/phone-number.spec.html: -------------------------------------------------------------------------------- 1 | 3 | phone-number.spec documentation

phone-number.spec

added in 8.12.4-0

Public specs of phone-number library.

begins-with-plus?

added in 8.12.4-1

(begins-with-plus? s)

Helper that returns true if a string has the + character before any digit.

info-keys

not-begins-with-plus?

added in 8.12.4-1

(not-begins-with-plus? s)

Complementary to begins-with-plus?

phone-gen

added in 8.12.4-1

(phone-gen options)

Phone number generator for specs. Options map: :region, :type, :predicate, :retries, :min-digits, :locale, :random-seed, :early-shrinking :preserve-raw

phone-spec

macro

(phone-spec f)(phone-spec f options)

Template macro for constructing specs with generators for the given predicate. It uses the generate function from phone-number.core to support generation of samples that are meeting the criteria.

random-format

(random-format n)

random-format-global

(random-format-global n)

random-format-regional

(random-format-regional n)

random-region-code

(random-region-code)

random-region-code-arg

(random-region-code-arg)

short-info-keys

-------------------------------------------------------------------------------- /docs/phone-number.tz-format.html: -------------------------------------------------------------------------------- 1 | 3 | phone-number.tz-format documentation

phone-number.tz-format

added in 8.12.4-0

Time zone formats for phone-number.

4 |

all

added in 8.12.4-0

Map of time zone formats (keywords) to TextStyle objects for time zone formatting.

5 |

all-arg

added in 8.12.16-1

Map of TextStyle objects to time zone formats (keywords) for time zone formatting (to be used as arguments).

6 |

all-arg-vec

added in 8.12.16-1

Vector of time zone formats (keywords) to be used as arguments.

7 |

all-vec

added in 8.12.4-0

Vector of time zone formats (keywords).

8 |

by-val

added in 8.12.16-1

Map of time zone formats to TextStyle objects.

9 |

by-val-arg

added in 8.12.16-1

Map of time zone formats as TextStyle objects mapped to keywords (values accepted by Libphonenumber methods).

10 |

by-val-arg-vec

added in 8.12.16-1

Vector of time zone values suitable to be passed as arguments to methods of Libphonenumber.

11 |

by-val-vec

added in 8.12.16-1

Vector of time zone values.

12 |

default

added in 8.12.4-0

default-val

added in 8.12.4-0

parse

added in 8.12.4-0

(parse k)(parse k use-infer)

Parses a time zone format specification and returns a value that can be supplied to phone-number functions. If nil is given it returns the default value.

13 |

transform

added in 8.12.4-0

(transform zone-id l style)

For the given Locale object and TextStyle object renders a string describing a time zone identifier (given as a string) passed as the first argument. If the style is nil then the original object passed as a zone-id argument is returned.

14 |

valid-arg?

added in 8.12.16-1

(valid-arg? tz-format)(valid-arg? tz-format use-infer)

Returns true if the given tz-format is valid as an argument, false otherwise.

15 |

valid?

added in 8.12.4-0

(valid? tz-format)(valid? tz-format use-infer)

Returns true if the given tz-format is valid, false otherwise.

16 |
-------------------------------------------------------------------------------- /phone-number.jar.asc: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP SIGNATURE----- 2 | Comment: GPGTools - http://gpgtools.org 3 | 4 | iQIzBAABCAAdFiEElzhGBxSaMDOq9Z/XNjF6dNg249AFAmP7QjwACgkQNjF6dNg2 5 | 49BaDRAA6w+gwD5Z4GkN8HNrsp3KI8trqGDonrJFJrG4dLgsMeokDtjf9iRsUaxY 6 | FwZlXqRcrtK7of154vSmgoIfcU2AO+RsIiv5GsVkLozYdmLmlQw4016/+HqKcfHv 7 | P3ilmrMtynTZgPxU2F67RJm24N82wja3GxfaekrvtZAAIVjHe1s22nZAbBSSH+eI 8 | NGy9aGaRKVFuJKB5VQnwS0euSjP6zDhyMNKKSGvxTNtLVPNEWJtWotCwfMMVKc4O 9 | 32DQ8Zas+xrRzBWMvfav12lfsSJMN4nGshLS6oDrDFrIwWl82Bw9geDI9VZ/4gIi 10 | sCyVL4UuzPQEUNchlgAUL90UIfm5t5BaWbe6aw7r210OVPoJxv5a6xCXnDphmYnR 11 | yqSEwWm/e/6OVaMPr6Y4RzzhJlfTjqyD1YqpdtGK24mSrvFunGg4w6AO+BhsBig/ 12 | WbVK3eVtZhyTYgW9zOP6GydQPcLO57qqzrJqRjf5uwe7iMZnSP0iw2/zZtVs5Tmp 13 | 8akQ0KRPpCeKbUUwRcyUuknCVQQOTO30neou2pHXPZdaQJCQ32NghKXxprDXm8Dy 14 | wYt76c/zk4Ku4fbce5xGMyH7Lg4CSQz8gVVpIB/RbnYJyKdm+KGyoovu4QUWXyl1 15 | nZLKac/Moo6OFjfl3SpjLwiRJu6eWIFAsTDbWp21me3u7hI7SjI= 16 | =76ne 17 | -----END PGP SIGNATURE----- 18 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | io.randomseed 5 | phone-number 6 | jar 7 | 8.13.6-3 8 | phone-number 9 | Creation, validation and inspection of phone numbers 10 | https://randomseed.io/software/phone-number/ 11 | 12 | 13 | LGPL License 14 | https://opensource.org/licenses/lgpl-3.0.html 15 | 16 | 17 | 18 | scm:git:git://github.com/randomseed-io/phone-number.git 19 | scm:git:ssh://git@github.com/randomseed-io/phone-number.git 20 | 8.13.6-3 21 | https://github.com/randomseed-io/phone-number/ 22 | 23 | 24 | 25 | org.clojure 26 | clojure 27 | 1.11.1 28 | 29 | 30 | com.googlecode.libphonenumber 31 | geocoder 32 | 2.200 33 | 34 | 35 | com.googlecode.libphonenumber 36 | carrier 37 | 1.190 38 | 39 | 40 | malabarba 41 | lazy-map 42 | 1.3 43 | 44 | 45 | com.googlecode.libphonenumber 46 | libphonenumber 47 | 8.13.6 48 | 49 | 50 | com.googlecode.libphonenumber 51 | prefixmapper 52 | 2.200 53 | 54 | 55 | org.clojure 56 | core.memoize 57 | 1.0.257 58 | 59 | 60 | trptr 61 | java-wrapper 62 | 0.2.3 63 | 64 | 65 | 66 | src 67 | test 68 | 69 | 70 | resources 71 | 72 | 73 | 74 | 75 | resources 76 | 77 | 78 | 79 | 80 | org.apache.maven.plugins 81 | maven-gpg-plugin 82 | 1.6 83 | 84 | 85 | sign-artifacts 86 | verify 87 | 88 | sign 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | clojars 98 | https://repo.clojars.org/ 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /pom.xml.asc: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP SIGNATURE----- 2 | Comment: GPGTools - http://gpgtools.org 3 | 4 | iQIzBAABCAAdFiEElzhGBxSaMDOq9Z/XNjF6dNg249AFAmP7QkMACgkQNjF6dNg2 5 | 49BnLhAAw0guryl6Q5hlWsgTTxGgifCXefTRmfrSWA9+rW0eM+3I/yTg8/b7unnG 6 | qtFSPjN+FAH1v10xeREnH+UAGxPhdj4uzQ1mdI8TuiQ4Meaq1MurFOwSoS0ragx3 7 | i9K20xtW6DLDAsLfkwfNeU+tANvKKm4gX5+kSHcGHkwBuiHuC3dnNqrEbY9K3afN 8 | z7VwaLv5Ex4JoMj6m9aJrpc3BBnRRVbCAHQYAQffKVY30vRbpZ/m1QvD8cdkrcA1 9 | FMHRQhtKzhfSzDQcGdhxk647EnWIZlUnLuWOqkfZXpYfjWQfeLluSix89s9joMKR 10 | o+GtiAybvTGv/iYET6lRUMhpCsMZjN0fLH1uqFmo0Te/fyPrYFwuGHMl0ntc57Op 11 | 1d+jfMjtq4/9p6S/+ZhfEqNoqyxvJ+ezPdONJyq5zFoM/l3JbKa9E+YeTlNS0ENC 12 | Yhzx8NSP2QnZ7C1KmuKTNs315cGfm70Z4/xKa2XfKJL7jmURthd+RcSfeAQ+Iv0o 13 | 5ivMd/ELD3zO5Z5hVJnVAH5pPUfx7uR6fvyKTFDmb9772aef/WEBDteGgzY1PpH7 14 | 8AMaGKR2o+Z8+v05LxWnqRS1vHHBVb73T+dPRj808By1pUvQICXzBACkqdpcWdwU 15 | g4kivuXTphVPgu3Z7lcCt74vOiC/2uShLftN81pEhLazfgpVq3w= 16 | =Jm6y 17 | -----END PGP SIGNATURE----- 18 | -------------------------------------------------------------------------------- /resources/codox/theme/randomseed/css/randomseed.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Open+Sans&display=swap'); 2 | 3 | body { 4 | font-family: 'Open Sans', 'Helvetica Neue', 'PT Sans', Helvetica, sans-serif; 5 | font-size: 15.5px; 6 | } 7 | 8 | pre, code { 9 | font-size: 10pt; 10 | } 11 | 12 | .sidebar.primary { 13 | background: #e2e2e2; 14 | border-right: solid 1px #cccccc; 15 | } 16 | 17 | .sidebar.primary li.current a { 18 | border-left: 3px solid #a33; 19 | color: #a33; 20 | } 21 | 22 | .sidebar a { 23 | color: #333; 24 | } 25 | 26 | .sidebar h3.no-link { 27 | color: #636363; 28 | } 29 | -------------------------------------------------------------------------------- /resources/codox/theme/randomseed/theme.edn: -------------------------------------------------------------------------------- 1 | {:transforms 2 | [[:head] 3 | [:append 4 | [:link {:rel "stylesheet", :type "text/css" :href "css/randomseed.css"}]] 5 | ] 6 | 7 | :resources 8 | ["css/randomseed.css"]} 9 | -------------------------------------------------------------------------------- /src/phone_number.clj: -------------------------------------------------------------------------------- 1 | (ns 2 | 3 | ^{:doc "Clojure interface to Libphonenumber." 4 | :author "Paweł Wilk" 5 | :added "8.12.4-2"} 6 | 7 | phone-number) 8 | 9 | (comment 10 | nil) 11 | -------------------------------------------------------------------------------- /src/phone_number/calling_code.clj: -------------------------------------------------------------------------------- 1 | (ns 2 | 3 | ^{:doc "Calling codes handling for phone-number." 4 | :author "Paweł Wilk" 5 | :added "8.12.4-0"} 6 | 7 | phone-number.calling-code 8 | 9 | (:require [clojure.set] 10 | [phone-number.util :as util] 11 | [phone-number.country-code :as country-code] 12 | [phone-number.net-code :as net-code]) 13 | 14 | (:import [com.google.i18n.phonenumbers 15 | PhoneNumberUtil 16 | NumberParseException])) 17 | 18 | ;; 19 | ;; Supported Calling Codes 20 | ;; 21 | 22 | (def ^{:added "8.12.4-0" 23 | :tag clojure.lang.PersistentHashSet} 24 | all 25 | "Set of supported calling codes." 26 | (clojure.set/union country-code/all net-code/all)) 27 | 28 | (def ^{:added "8.12.4-0" 29 | :tag clojure.lang.PersistentHashSet} 30 | by-val 31 | "Set of supported calling codes (values)." 32 | all) 33 | 34 | (def ^{:added "8.12.16-1" 35 | :tag clojure.lang.PersistentHashSet} 36 | all-arg 37 | "Set of supported calling codes to be passed as arguments." 38 | (clojure.set/union country-code/all-arg net-code/all-arg)) 39 | 40 | (def ^{:added "8.12.16-1" 41 | :tag clojure.lang.PersistentHashSet} 42 | by-val-arg 43 | "Set of supported calling codes (values) to be passed as arguments." 44 | all-arg) 45 | 46 | (def ^{:added "8.12.4-0" 47 | :tag clojure.lang.PersistentVector} 48 | all-vec 49 | "Vector of all supported calling codes." 50 | (vec all)) 51 | 52 | (def ^{:added "8.12.16-1" 53 | :tag clojure.lang.PersistentVector} 54 | all-arg-vec 55 | "Vector of all supported calling codes to be used as arguments." 56 | (vec all-arg)) 57 | 58 | (def ^{:added "8.12.4-0" 59 | :tag clojure.lang.PersistentVector} 60 | by-val-vec 61 | "Vector of all supported calling codes." 62 | (vec by-val)) 63 | 64 | (def ^{:added "8.12.16-1" 65 | :tag clojure.lang.PersistentVector} 66 | by-val-arg-vec 67 | "Vector of all supported calling codes." 68 | all-arg-vec) 69 | 70 | (defn valid? 71 | "Returns true if the given region-specification is a valid region code, false 72 | otherwise." 73 | {:added "8.12.4-0" :tag Boolean} 74 | [^Integer calling-code] 75 | (contains? all calling-code)) 76 | 77 | (defn valid-arg? 78 | "Returns true if the given region-specification is a valid region code to be used as 79 | an argument, false otherwise." 80 | {:added "8.12.16-1" :tag Boolean} 81 | [^Integer calling-code] 82 | (contains? all-arg calling-code)) 83 | 84 | (defn parse 85 | "Parses a calling code and returns a value that can be supplied to 86 | Libphonenumber methods." 87 | {:added "8.12.4-0" :tag Integer} 88 | ([^Integer calling-code] 89 | (assert (valid-arg? calling-code) 90 | (str "Calling code " calling-code " is not valid")) 91 | calling-code)) 92 | 93 | (defn generate-sample 94 | "Generates a random calling code." 95 | {:added "8.12.4-0" :tag Integer} 96 | ([] (rand-nth all-vec)) 97 | ([^java.util.Random rng] (util/get-rand-nth all-vec rng))) 98 | 99 | (defn generate-sample-val 100 | "Generates a random calling code." 101 | {:added "8.12.16-1" :tag Integer} 102 | ([] (rand-nth by-val-vec)) 103 | ([^java.util.Random rng] (util/get-rand-nth by-val-vec rng))) 104 | 105 | (defn generate-arg-sample 106 | "Generates random calling code." 107 | {:added "8.12.16-1" :tag Integer} 108 | ([] (rand-nth all-arg-vec)) 109 | ([^java.util.Random rng] (util/get-rand-nth all-arg-vec rng))) 110 | 111 | (defn generate-arg-sample-val 112 | "Generates random calling code." 113 | {:added "8.12.16-1" :tag Integer} 114 | ([] (rand-nth by-val-arg-vec)) 115 | ([^java.util.Random rng] (util/get-rand-nth by-val-arg-vec rng))) 116 | -------------------------------------------------------------------------------- /src/phone_number/cost.clj: -------------------------------------------------------------------------------- 1 | (ns 2 | 3 | ^{:doc "Cost classes of short numbers for phone-number." 4 | :author "Paweł Wilk" 5 | :added "8.12.4-0"} 6 | 7 | phone-number.cost 8 | 9 | (:require [clojure.set] 10 | [phone-number.util :as util]) 11 | 12 | (:import [com.google.i18n.phonenumbers 13 | ShortNumberInfo 14 | ShortNumberInfo$ShortNumberCost])) 15 | 16 | (def ^{:added "8.12.4-0" 17 | :tag clojure.lang.PersistentArrayMap} 18 | all 19 | "Map of phone number cost (keywords) to ShortNumberCost values." 20 | #::{:toll-free ShortNumberInfo$ShortNumberCost/TOLL_FREE 21 | :standard ShortNumberInfo$ShortNumberCost/STANDARD_RATE 22 | :premium ShortNumberInfo$ShortNumberCost/PREMIUM_RATE 23 | :unknown ShortNumberInfo$ShortNumberCost/UNKNOWN_COST}) 24 | 25 | (def ^{:added "8.12.16-1" 26 | :const true 27 | :tag clojure.lang.Keyword} 28 | unknown ::unknown) 29 | 30 | (def ^{:added "8.12.16-1" 31 | :const true 32 | :tag String} 33 | unknown-val (all unknown)) 34 | 35 | (def ^{:added "8.12.4-0" 36 | :const true 37 | :tag clojure.lang.Keyword} 38 | default ::standard) 39 | 40 | (def ^{:added "8.12.4-0" 41 | :tag ShortNumberInfo$ShortNumberCost} 42 | default-val (all default)) 43 | 44 | (def ^{:added "8.12.4-0" 45 | :tag clojure.lang.PersistentArrayMap} 46 | all-arg 47 | "Map of ShortNumberCost values to phone number costs (keywords) suitable to be passed 48 | as arguments." 49 | (dissoc all ::unknown)) 50 | 51 | (def ^{:added "8.12.4-0" 52 | :tag clojure.lang.PersistentArrayMap} 53 | by-val 54 | "Map of ShortNumberCost values to phone number costs (keywords)." 55 | (clojure.set/map-invert all)) 56 | 57 | (def ^{:added "8.12.16-1" 58 | :tag clojure.lang.PersistentArrayMap} 59 | by-val-arg 60 | "Map of ShortNumberCost values to phone number costs (keywords) suitable to be passed 61 | as method argument." 62 | (clojure.set/map-invert all-arg)) 63 | 64 | (def ^{:added "8.12.4-0" 65 | :tag clojure.lang.PersistentVector} 66 | all-vec 67 | "Vector of costs (keywords)." 68 | (vec (keys all))) 69 | 70 | (def ^{:added "8.12.4-0" 71 | :tag clojure.lang.PersistentVector} 72 | all-arg-vec 73 | "Vector of costs (keywords) suitable as arguments." 74 | (vec (keys all-arg))) 75 | 76 | (def ^{:added "8.12.4-0" 77 | :tag ShortNumberInfo$ShortNumberCost} 78 | by-val-vec 79 | "Vector of costs (ShortNumberCost values)." 80 | (vec (keys by-val))) 81 | 82 | (def ^{:added "8.12.16-1" 83 | :tag ShortNumberInfo$ShortNumberCost} 84 | by-val-arg-vec 85 | "Vector of costs (ShortNumberCost values)." 86 | (vec (keys by-val-arg))) 87 | 88 | (defn valid? 89 | "Returns true if the given cost is valid, false otherwise." 90 | {:added "8.12.4-0" :tag Boolean} 91 | ([^clojure.lang.Keyword cost] 92 | (contains? all cost)) 93 | ([^clojure.lang.Keyword cost 94 | ^Boolean use-infer] 95 | (contains? all (util/ns-infer "phone-number.cost" cost use-infer)))) 96 | 97 | (defn valid-arg? 98 | "Returns true if the given cost is valid, false otherwise." 99 | {:added "8.12.4-0" :tag Boolean} 100 | ([^clojure.lang.Keyword cost] 101 | (contains? all-arg cost)) 102 | ([^clojure.lang.Keyword cost 103 | ^Boolean use-infer] 104 | (contains? all-arg (util/ns-infer "phone-number.cost" cost use-infer)))) 105 | 106 | (defn parse 107 | "Parses a cost and returns a value that can be supplied to Libphonenumber methods. If 108 | nil is given it returns the default value." 109 | {:added "8.12.4-0" :tag ShortNumberInfo$ShortNumberCost} 110 | ([^clojure.lang.Keyword k] 111 | (parse k true)) 112 | ([^clojure.lang.Keyword k 113 | ^Boolean use-infer] 114 | (if (nil? k) 115 | default-val 116 | (let [k (util/ns-infer "phone-number.cost" k use-infer)] 117 | (assert (valid-arg? k) (str "Cost class " k " is not valid")) 118 | (all-arg k))))) 119 | 120 | (defn generate-sample 121 | "Generates random number cost." 122 | {:added "8.12.4-0" :tag clojure.lang.Keyword} 123 | ([] (rand-nth all-vec)) 124 | ([^java.util.Random rng] (util/get-rand-nth all-vec rng))) 125 | 126 | (defn generate-sample-val 127 | "Generates random number cost (ShortNumberCost value)." 128 | {:added "8.12.4-0" :tag ShortNumberInfo$ShortNumberCost} 129 | ([] (rand-nth by-val-vec)) 130 | ([^java.util.Random rng] (util/get-rand-nth by-val-vec rng))) 131 | -------------------------------------------------------------------------------- /src/phone_number/country_code.clj: -------------------------------------------------------------------------------- 1 | (ns 2 | 3 | ^{:doc "Country calling codes handling for phone-number." 4 | :author "Paweł Wilk" 5 | :added "8.12.4-0"} 6 | 7 | phone-number.country-code 8 | 9 | (:require [clojure.set] 10 | [phone-number.util :as util]) 11 | 12 | (:import [com.google.i18n.phonenumbers 13 | PhoneNumberUtil 14 | NumberParseException])) 15 | 16 | ;; 17 | ;; Supported Country Calling Codes 18 | ;; 19 | 20 | (def ^{:added "8.12.4-0" 21 | :tag clojure.lang.PersistentHashSet} 22 | all 23 | "Set of supported country codes." 24 | (clojure.set/difference 25 | (set (.getSupportedCallingCodes (util/instance))) 26 | (set (.getSupportedGlobalNetworkCallingCodes (util/instance))))) 27 | 28 | (def ^{:added "8.12.4-0" 29 | :tag clojure.lang.PersistentHashSet} 30 | all-arg 31 | "Set of supported country codes (to be used as arguments)." 32 | all) 33 | 34 | (def ^{:added "8.12.4-0" 35 | :tag clojure.lang.PersistentHashSet} 36 | by-val 37 | "Set of supported values of country codes." 38 | all) 39 | 40 | (def ^{:added "8.12.4-0" 41 | :tag clojure.lang.PersistentHashSet} 42 | by-val-arg 43 | "Set of supported values of country codes (to be used as method arguments)." 44 | all-arg) 45 | 46 | (def ^{:added "8.12.4-0" 47 | :tag clojure.lang.PersistentVector} 48 | all-vec 49 | "Vector of all supported country codes." 50 | (vec all)) 51 | 52 | (def ^{:added "8.12.4-0" 53 | :tag clojure.lang.PersistentVector} 54 | by-val-vec 55 | "Vector of all supported country codes." 56 | (vec by-val)) 57 | 58 | (def ^{:added "8.12.16-1" 59 | :tag clojure.lang.PersistentVector} 60 | all-arg-vec 61 | "Vector of all supported country codes (valid as args)." 62 | (vec all-arg)) 63 | 64 | (def ^{:added "8.12.16-1" 65 | :tag clojure.lang.PersistentVector} 66 | by-val-arg-vec 67 | "Vector of all supported country codes (valid as args)." 68 | (vec by-val-arg)) 69 | 70 | (defn valid? 71 | "Returns true if the given region-specification is a valid region code, false 72 | otherwise." 73 | {:added "8.12.4-0" :tag Boolean} 74 | [^Integer calling-code] 75 | (contains? all calling-code)) 76 | 77 | (defn valid-arg? 78 | "Returns true if the given region-specification is a valid region code (to be used as 79 | an argument), false otherwise." 80 | {:added "8.12.16-1" :tag Boolean} 81 | [^Integer calling-code] 82 | (contains? all-arg calling-code)) 83 | 84 | (defn parse 85 | "Parses a country calling code and returns a value that can be supplied to 86 | Libphonenumber methods." 87 | {:added "8.12.4-0" :tag Integer} 88 | ([^Integer calling-code] 89 | (assert (valid-arg? calling-code) 90 | (str "Country code " calling-code " is not valid")) 91 | calling-code)) 92 | 93 | (defn generate-sample 94 | "Generates a random country calling code." 95 | {:added "8.12.4-0" :tag Integer} 96 | ([] (rand-nth all-vec)) 97 | ([^java.util.Random rng] (util/get-rand-nth all-vec rng))) 98 | 99 | (defn generate-sample-val 100 | "Generates a random country calling code." 101 | {:added "8.12.16-1" :tag Integer} 102 | ([] (rand-nth by-val-vec)) 103 | ([^java.util.Random rng] (util/get-rand-nth by-val-vec rng))) 104 | 105 | (defn generate-arg-sample 106 | "Generates a random country calling code." 107 | {:added "8.12.16-1" :tag Integer} 108 | ([] (rand-nth all-arg-vec)) 109 | ([^java.util.Random rng] (util/get-rand-nth all-arg-vec rng))) 110 | 111 | (defn generate-arg-sample-val 112 | "Generates a random country calling code." 113 | {:added "8.12.16-1" :tag Integer} 114 | ([] (rand-nth by-val-arg-vec)) 115 | ([^java.util.Random rng] (util/get-rand-nth by-val-arg-vec rng))) 116 | -------------------------------------------------------------------------------- /src/phone_number/dialing_region.clj: -------------------------------------------------------------------------------- 1 | (ns 2 | 3 | ^{:doc "Clojure interface to Libphonenumber, dialing region." 4 | :author "Paweł Wilk" 5 | :added "8.12.4-2" 6 | :no-doc true} 7 | 8 | phone-number.dialing-region) 9 | 10 | (comment 11 | nil) 12 | -------------------------------------------------------------------------------- /src/phone_number/format.clj: -------------------------------------------------------------------------------- 1 | (ns 2 | 3 | ^{:doc "Phone number formats for phone-number." 4 | :author "Paweł Wilk" 5 | :added "8.12.4-0"} 6 | 7 | phone-number.format 8 | 9 | (:require [clojure.set] 10 | [phone-number.util :as util]) 11 | 12 | (:import [com.google.i18n.phonenumbers 13 | PhoneNumberUtil 14 | PhoneNumberUtil$PhoneNumberFormat])) 15 | 16 | (def ^{:added "8.12.4-0" 17 | :tag clojure.lang.PersistentArrayMap} 18 | all 19 | "Map of possible format identifiers (keywords) to PhoneNumberFormat values 20 | plus an additional value indicating raw input." 21 | #::{:e164 PhoneNumberUtil$PhoneNumberFormat/E164 22 | :international PhoneNumberUtil$PhoneNumberFormat/INTERNATIONAL 23 | :national PhoneNumberUtil$PhoneNumberFormat/NATIONAL 24 | :rfc3966 PhoneNumberUtil$PhoneNumberFormat/RFC3966 25 | :raw-input ::raw}) 26 | 27 | (def ^{:added "8.12.16-1" 28 | :const true 29 | :tag clojure.lang.Keyword} 30 | raw ::raw-input) 31 | 32 | (def ^{:added "8.12.16-1" 33 | :const true 34 | :tag String} 35 | raw-val (all raw)) 36 | 37 | (def ^{:added "8.12.4-0" 38 | :const true 39 | :tag clojure.lang.Keyword} 40 | default ::international) 41 | 42 | (def ^{:added "8.12.4-0" 43 | :tag PhoneNumberUtil$PhoneNumberFormat} 44 | default-val (all default)) 45 | 46 | (def ^{:added "8.12.16-1" 47 | :tag clojure.lang.PersistentArrayMap} 48 | all-arg 49 | "Map of possible format identifiers (keywords) to PhoneNumberFormat values 50 | (plus an additional value indicating raw input) suitable to be used as arguments." 51 | all) 52 | 53 | (def ^{:added "8.12.4-0" 54 | :tag clojure.lang.PersistentArrayMap} 55 | by-val 56 | "Map of possible PhoneNumberFormat values (plus an additional value indicating raw 57 | input) to format identifiers (keywords) suitable to be used as arguments." 58 | (clojure.set/map-invert all)) 59 | 60 | (def ^{:added "8.12.16-1" 61 | :tag clojure.lang.PersistentArrayMap} 62 | by-val-arg 63 | "Map of possible PhoneNumberFormat values to format identifiers (keywords) suitable 64 | to be used as arguments for methods of Libphonenumber." 65 | (clojure.set/map-invert (dissoc all-arg :raw-input))) 66 | 67 | (def ^{:added "8.12.16-1" 68 | :tag clojure.lang.PersistentVector} 69 | all-vec 70 | "Vector of formats (keywords)." 71 | (vec (keys all))) 72 | 73 | (def ^{:added "8.12.16-1" 74 | :tag clojure.lang.PersistentVector} 75 | all-arg-vec 76 | "Vector of formats (keywords) suitable to be used as arguments." 77 | all-vec) 78 | 79 | (def ^{:added "8.12.4-0" 80 | :tag clojure.lang.PersistentVector} 81 | by-val-vec 82 | "Vector of formats (PhoneNumberFormat values + additional value indicating raw format 83 | as keyword)." 84 | (vec (keys by-val))) 85 | 86 | (def ^{:added "8.12.16-1" 87 | :tag clojure.lang.PersistentVector} 88 | by-val-arg-vec 89 | "Vector of formats (PhoneNumberFormat values)." 90 | (vec (keys by-val-arg))) 91 | 92 | (def ^{:added "8.12.4-0" 93 | :tag clojure.lang.PersistentHashSet} 94 | global 95 | "Set of formats (keywords) that should identify values containing country code information." 96 | #{::e164 ::international ::rfc3966}) 97 | 98 | (def ^{:added "8.12.4-0" 99 | :tag clojure.lang.PersistentHashSet} 100 | regional 101 | "Set of formats (keywords) that should identify values containing country code information." 102 | (clojure.set/difference (set (keys all)) global #{raw})) 103 | 104 | (def ^{:added "8.12.4-1" 105 | :tag clojure.lang.PersistentVector} 106 | global-vec 107 | "Vector of formats (keywords)." 108 | (vec global)) 109 | 110 | (def ^{:added "8.12.4-1" 111 | :tag clojure.lang.PersistentVector} 112 | regional-vec 113 | "Vector of formats (keywords)." 114 | (vec regional)) 115 | 116 | (defn valid? 117 | "Returns true if the given format is valid, false otherwise." 118 | {:added "8.12.4-0" :tag Boolean} 119 | ([^clojure.lang.Keyword format] 120 | (contains? all format)) 121 | ([^clojure.lang.Keyword format 122 | ^Boolean use-infer] 123 | (contains? all (util/ns-infer "phone-number.format" format use-infer)))) 124 | 125 | (defn valid-arg? 126 | "Returns true if the given format is valid, false otherwise." 127 | {:added "8.12.4-0" :tag Boolean} 128 | ([^clojure.lang.Keyword format] 129 | (contains? all-arg format)) 130 | ([^clojure.lang.Keyword format 131 | ^Boolean use-infer] 132 | (contains? all-arg (util/ns-infer "phone-number.format" format use-infer)))) 133 | 134 | (defn parse 135 | "Parses a format specification and returns a value that can be supplied to 136 | Libphonenumber methods." 137 | {:added "8.12.4-0" :tag PhoneNumberUtil$PhoneNumberFormat} 138 | ([^clojure.lang.Keyword k] 139 | (parse k true)) 140 | ([^clojure.lang.Keyword k 141 | ^Boolean use-infer] 142 | (if (nil? k) 143 | default-val 144 | (let [k (util/ns-infer "phone-number.format" k use-infer)] 145 | (assert (valid-arg? k) (str "Format specification " k " is not valid")) 146 | (all k))))) 147 | 148 | (defn global? 149 | "Returns true if the given format contains country code information, false otherwise." 150 | {:added "8.12.4-0" :tag Boolean} 151 | ([^clojure.lang.Keyword format] 152 | (contains? global format)) 153 | ([^clojure.lang.Keyword format 154 | ^Boolean use-infer] 155 | (contains? global (util/ns-infer "phone-number.format" format use-infer)))) 156 | 157 | (defn regional? 158 | "Returns true if the given format does not contain country code information, false 159 | otherwise." 160 | {:added "8.12.4-0" :tag Boolean} 161 | ([^clojure.lang.Keyword format] 162 | (contains? regional format)) 163 | ([^clojure.lang.Keyword format 164 | ^Boolean use-infer] 165 | (contains? regional (util/ns-infer "phone-number.format" format use-infer)))) 166 | 167 | ;; 168 | ;; Backward compatibility 169 | ;; 170 | 171 | (def ^{:added "8.12.4-0" 172 | :deprecated "8.12.4-1" 173 | :tag clojure.lang.PersistentHashSet} 174 | calling-coded 175 | "DEPRECATED: use `global`" 176 | global) 177 | 178 | (def ^{:added "8.12.4-0" 179 | :deprecated "8.12.4-1" 180 | :tag Boolean 181 | :arglists '([^clojure.lang.Keyword format])} 182 | calling-coded? 183 | "DEPRECATED: use `global?`" 184 | global?) 185 | 186 | (def ^{:added "8.12.4-0" 187 | :deprecated "8.12.4-1" 188 | :tag clojure.lang.PersistentHashSet} 189 | not-calling-coded 190 | "DEPRECATED: use `regional`" 191 | regional) 192 | 193 | (def ^{:added "8.12.4-0" 194 | :deprecated "8.12.4-1" 195 | :tag Boolean 196 | :arglists '([^clojure.lang.Keyword format])} 197 | not-calling-coded? 198 | "DEPRECATED: use `regional?`" 199 | regional?) 200 | -------------------------------------------------------------------------------- /src/phone_number/leniency.clj: -------------------------------------------------------------------------------- 1 | (ns 2 | 3 | ^{:doc "Leniency types for phone-number" 4 | :author "Paweł Wilk" 5 | :added "8.12.4-3"} 6 | 7 | phone-number.leniency 8 | 9 | (:require [clojure.set] 10 | [phone-number.util :as util]) 11 | 12 | (:import [com.google.i18n.phonenumbers 13 | PhoneNumberUtil 14 | PhoneNumberUtil$Leniency])) 15 | 16 | (def ^{:added "8.12.4-3" 17 | :tag clojure.lang.PersistentArrayMap} 18 | all 19 | "Map of leniencies (keywords) to Leniency values." 20 | #::{:exact PhoneNumberUtil$Leniency/EXACT_GROUPING 21 | :possible PhoneNumberUtil$Leniency/POSSIBLE 22 | :strict PhoneNumberUtil$Leniency/STRICT_GROUPING 23 | :valid PhoneNumberUtil$Leniency/VALID}) 24 | 25 | (def ^{:added "8.12.16-1" 26 | :tag clojure.lang.PersistentVector} 27 | all-arg 28 | "Vector of leniencies (keywords) to be used as arguments." 29 | all) 30 | 31 | (def ^{:added "8.12.4-3" 32 | :tag clojure.lang.PersistentArrayMap} 33 | by-val 34 | "Map of Leniency values to leniencies (keywords)." 35 | (clojure.set/map-invert all)) 36 | 37 | (def ^{:added "8.12.16-1" 38 | :tag clojure.lang.PersistentArrayMap} 39 | by-val-arg 40 | "Map of Leniency values to leniencies (keywords) to be used as method arguments." 41 | (clojure.set/map-invert all-arg)) 42 | 43 | (def ^{:added "8.12.4-3" 44 | :tag clojure.lang.PersistentVector} 45 | all-vec 46 | "Vector of leniencies (keywords)." 47 | (vec (keys all))) 48 | 49 | (def ^{:added "8.12.16-1" 50 | :tag clojure.lang.PersistentVector} 51 | all-arg-vec 52 | "Vector of leniencies (keywords) to be used as arguments." 53 | (vec (keys all-arg))) 54 | 55 | (def ^{:added "8.12.4-3" 56 | :tag clojure.lang.PersistentVector} 57 | by-val-vec 58 | "Vector of leniencies (Leniency values)." 59 | (vec (keys by-val))) 60 | 61 | (def ^{:added "8.12.16-1" 62 | :tag clojure.lang.PersistentVector} 63 | by-val-arg-vec 64 | "Vector of leniencies (Leniency values) to be used as method arguments." 65 | (vec (keys by-val-arg))) 66 | 67 | (def ^{:added "8.12.4-3" 68 | :const true 69 | :tag clojure.lang.Keyword} 70 | default ::valid) 71 | 72 | (def ^{:added "8.12.4-3" 73 | :tag PhoneNumberUtil$Leniency} 74 | default-val (all default)) 75 | 76 | (defn valid? 77 | "Returns true if the given leniency is a valid leniency, false 78 | otherwise. In its binary form it uses namespace inference." 79 | {:added "8.12.4-3" :tag Boolean} 80 | ([^clojure.lang.Keyword leniency] 81 | (contains? all leniency)) 82 | ([^clojure.lang.Keyword leniency 83 | ^Boolean use-infer] 84 | (contains? all (util/ns-infer "phone-number.leniency" leniency use-infer)))) 85 | 86 | (defn valid-arg? 87 | "Returns true if the given leniency is a valid leniency to be used as an argument, 88 | false otherwise. In its binary form it uses namespace inference." 89 | {:added "8.12.16-1" :tag Boolean} 90 | ([^clojure.lang.Keyword leniency] 91 | (contains? all-arg leniency)) 92 | ([^clojure.lang.Keyword leniency 93 | ^Boolean use-infer] 94 | (contains? all-arg (util/ns-infer "phone-number.leniency" leniency use-infer)))) 95 | 96 | (defn parse 97 | "Parses a leniency and returns a value that can be supplied to 98 | Libphonenumber methods." 99 | {:added "8.12.4-3" :tag PhoneNumberUtil$Leniency} 100 | ([^clojure.lang.Keyword k] 101 | (parse k true)) 102 | ([^clojure.lang.Keyword k 103 | ^Boolean use-infer] 104 | (if (nil? k) 105 | default-val 106 | (let [k (util/ns-infer "phone-number.leniency" k use-infer)] 107 | (assert (valid-arg? k) (str "Leniency specification " k " is not valid")) 108 | (all k))))) 109 | 110 | (defn generate-sample 111 | "Generates random leniency." 112 | {:added "8.12.4-3" :tag clojure.lang.Keyword} 113 | ([] (rand-nth all-vec)) 114 | ([^java.util.Random rng] (util/get-rand-nth all-vec rng))) 115 | 116 | (defn generate-sample-arg 117 | "Generates random leniency (suitable as an argument)." 118 | {:added "8.12.16-1" :tag clojure.lang.Keyword} 119 | ([] (rand-nth all-arg-vec)) 120 | ([^java.util.Random rng] (util/get-rand-nth all-arg-vec rng))) 121 | 122 | (defn generate-sample-val 123 | "Generates random leniency (string value)." 124 | {:added "8.12.4-3" :tag String} 125 | ([] (rand-nth by-val-vec)) 126 | ([^java.util.Random rng] (util/get-rand-nth by-val-vec rng))) 127 | 128 | (defn generate-sample-val-arg 129 | "Generates random leniency (string value, suitable as an argument)." 130 | {:added "8.12.16-1" :tag String} 131 | ([] (rand-nth by-val-arg-vec)) 132 | ([^java.util.Random rng] (util/get-rand-nth by-val-arg-vec rng))) 133 | -------------------------------------------------------------------------------- /src/phone_number/locale.clj: -------------------------------------------------------------------------------- 1 | (ns 2 | 3 | ^{:doc "Locale support for phone-number" 4 | :author "Paweł Wilk" 5 | :added "8.12.4-3"} 6 | 7 | phone-number.locale 8 | 9 | (:require [clojure.set] 10 | [phone-number.util :as util] 11 | [trptr.java-wrapper.locale :as l]) 12 | 13 | (:import [com.google.i18n.phonenumbers 14 | PhoneNumberUtil])) 15 | 16 | (def ^{:added "8.12.4-3" 17 | :const true 18 | :tag clojure.lang.Keyword} 19 | default ::default) 20 | 21 | (def ^{:added "8.12.4-3" 22 | :tag java.util.Locale} 23 | default-val (l/locale nil)) 24 | 25 | (def ^{:added "8.12.4-3" 26 | :tag clojure.lang.PersistentArrayMap} 27 | all 28 | "Map of locales (keywords) to Locale values." 29 | (assoc 30 | (into #::{} 31 | (map 32 | (juxt #(keyword "phone-number.locale" (str %)) identity) 33 | (filter #(seq (str %)) 34 | l/available-locales))) 35 | ::default 36 | default-val)) 37 | 38 | (def ^{:added "8.12.16-1" 39 | :tag clojure.lang.PersistentArrayMap} 40 | all-arg 41 | "Map of locales (keywords) to Locale values suitable to be passed as arguments." 42 | all) 43 | 44 | (def ^{:added "8.12.4-3" 45 | :tag clojure.lang.PersistentArrayMap} 46 | by-val 47 | "Map of Locale values to locales (keywords)." 48 | (clojure.set/map-invert all)) 49 | 50 | (def ^{:added "8.12.16-1" 51 | :tag clojure.lang.PersistentArrayMap} 52 | by-val-arg 53 | "Map of Locale values to locales (keywords) suitable to be passed as method 54 | arguments." 55 | by-val) 56 | 57 | 58 | (def ^{:added "8.12.4-3" 59 | :tag clojure.lang.PersistentHashSet} 60 | available 61 | "Set of available locale (keywords)." 62 | (set (keys all))) 63 | 64 | (def ^{:added "8.12.4-3" 65 | :tag clojure.lang.PersistentVector} 66 | all-vec 67 | "Vector of locales (keywords)." 68 | (vec (keys all))) 69 | 70 | (def ^{:added "8.12.16-1" 71 | :tag clojure.lang.PersistentVector} 72 | all-arg-vec 73 | "Vector of locales (keywords) suitable to be used as arguments." 74 | all-vec) 75 | 76 | (def ^{:added "8.12.4-3" 77 | :tag clojure.lang.PersistentVector} 78 | by-val-vec 79 | "Vector of locales (Locale values)." 80 | (vec (keys by-val))) 81 | 82 | (def ^{:added "8.12.16-1" 83 | :tag clojure.lang.PersistentVector} 84 | by-val-arg-vec 85 | "Vector of locales (Locale values) suitable to be used as method arguments." 86 | by-val-vec) 87 | 88 | (defn valid-arg? 89 | "Returns `true` if the given locale specification is valid and supported, `false` 90 | otherwise. For `nil` it returns `true` assuming it will be a default, system 91 | locale. If `strict` flag is set then for nil value it returns `false` and for 92 | keywords it only checks if they are in the locale 93 | map (`phone-number.locale/all`)." 94 | {:added "8.12.4-3" :tag Boolean} 95 | ([^java.util.Locale locale-specification] 96 | (valid-arg? locale-specification true false)) 97 | ([^java.util.Locale locale-specification 98 | ^Boolean use-infer] 99 | (if (nil? locale-specification) true 100 | (or 101 | (and (keyword? locale-specification) 102 | (contains? all (util/ns-infer "phone-number.locale" locale-specification use-infer))) 103 | (try (contains? by-val (l/locale locale-specification)) (catch Throwable e false))))) 104 | ([^java.util.Locale locale-specification 105 | ^Boolean use-infer 106 | ^Boolean strict] 107 | (if-not strict 108 | (valid-arg? locale-specification use-infer) 109 | (if (nil? locale-specification) false 110 | (if (keyword? locale-specification) 111 | (contains? all (util/ns-infer "phone-number.locale" locale-specification use-infer)) 112 | (try (contains? by-val (l/locale locale-specification)) (catch Throwable e false))))))) 113 | 114 | (defn strictly-valid-arg? 115 | "Returns `true` if the given locale specification is valid and supported, `false` 116 | otherwise. For `nil` it returns `false` and for keywords it only checks if they are 117 | in the locale map (`phone-number.locale/all`). If the key is not there, it returns 118 | `false`. Namespace inference is supported using the second argument (the default is 119 | not to infer)." 120 | {:added "8.12.4-3" :tag Boolean} 121 | ([^java.util.Locale locale-specification] 122 | (valid-arg? locale-specification false true)) 123 | ([^java.util.Locale locale-specification 124 | ^Boolean use-infer] 125 | (valid-arg? locale-specification use-infer true))) 126 | 127 | (def ^{:added "8.12.16-1" :tag Boolean 128 | :arglists '([^java.util.Locale locale-specification] 129 | [^java.util.Locale locale-specification 130 | ^Boolean use-infer] 131 | [^java.util.Locale locale-specification 132 | ^Boolean use-infer 133 | ^Boolean strict])} 134 | valid? 135 | "Returns `true` if the given locale specification is valid and supported, `false` 136 | otherwise. For `nil` it returns `true` assuming it will be a default, system 137 | locale. If `strict` flag is set then for nil value it returns `false` and for 138 | keywords it only checks if they are in the locale map (`phone-number.locale/all`)." 139 | valid-arg?) 140 | 141 | (def ^{:added "8.12.16-1" :tag Boolean 142 | :arglists '([^java.util.Locale locale-specification] 143 | [^java.util.Locale locale-specification 144 | ^Boolean use-infer])} 145 | strictly-valid? 146 | "Returns `true` if the given locale specification is valid and supported, `false` 147 | otherwise. For `nil` it returns `false` and for keywords it only checks if they are 148 | in the locale map (`phone-number.locale/all`). If the key is not there, it returns 149 | `false`. Namespace inference is supported using the second argument (the default is 150 | not to infer)." 151 | strictly-valid-arg?) 152 | 153 | (defn parse 154 | "Parses locale. If it is a `java.util.Locale` object it returns it. If it's not 155 | keyword then it parses it by calling `trptr.java-wrapper.locale/locale`. If it is a 156 | keyword it first tries to infer a namespace (if not present and the `use-infer` is 157 | set to some truthy value) and then looks it up in locales map. If the value is 158 | found, returns the associated `Locale` object. Otherwise it falls back to getting 159 | locale using the function from `trptr.java-wrapper.locale/locale` (before doing so 160 | it strips any namespace from a keyword, if found)." 161 | {:added "8.12.4-3" :tag java.util.Locale} 162 | ([^java.util.Locale locale-specification] 163 | (parse locale-specification true)) 164 | ([^java.util.Locale locale-specification 165 | ^Boolean use-infer] 166 | (if (instance? java.util.Locale locale-specification) locale-specification 167 | (if-not (keyword? locale-specification) (l/locale locale-specification) 168 | (if-some [lready (all-arg (util/ns-infer "phone-number.locale" locale-specification use-infer))] 169 | lready 170 | (l/locale locale-specification)))))) 171 | 172 | (defn generate-sample 173 | "Generates random locale." 174 | {:added "8.12.4-3" :tag clojure.lang.Keyword} 175 | ([] (rand-nth all-vec)) 176 | ([^java.util.Random rng] (util/get-rand-nth all-vec rng))) 177 | 178 | (defn generate-sample-val 179 | "Generates random locale (string value)." 180 | {:added "8.12.4-3" :tag String} 181 | ([] (rand-nth by-val-vec)) 182 | ([^java.util.Random rng] (util/get-rand-nth by-val-vec rng))) 183 | -------------------------------------------------------------------------------- /src/phone_number/match.clj: -------------------------------------------------------------------------------- 1 | (ns 2 | 3 | ^{:doc "Match types for phone-number" 4 | :author "Paweł Wilk" 5 | :added "8.12.4-0"} 6 | 7 | phone-number.match 8 | 9 | (:require [clojure.set] 10 | [lazy-map.core :refer :all]) 11 | 12 | (:import [com.google.i18n.phonenumbers 13 | PhoneNumberUtil 14 | PhoneNumberUtil$MatchType 15 | PhoneNumberMatch])) 16 | 17 | (def ^{:added "8.12.4-0" 18 | :tag clojure.lang.PersistentArrayMap} 19 | all 20 | "Map of phone number matches (keywords) to MatchType values." 21 | #::{:exact PhoneNumberUtil$MatchType/EXACT_MATCH 22 | :not-number PhoneNumberUtil$MatchType/NOT_A_NUMBER 23 | :short-nsn PhoneNumberUtil$MatchType/SHORT_NSN_MATCH 24 | :nsn PhoneNumberUtil$MatchType/NSN_MATCH 25 | :none PhoneNumberUtil$MatchType/NO_MATCH}) 26 | 27 | (def ^{:added "8.12.16-1" 28 | :const true 29 | :tag clojure.lang.Keyword} 30 | none ::none) 31 | 32 | (def ^{:added "8.12.16-1" 33 | :const true 34 | :tag String} 35 | none-val (all ::none)) 36 | 37 | (def ^{:added "8.12.16-1" 38 | :tag clojure.lang.PersistentArrayMap} 39 | all-arg 40 | "Map of phone number matches (keywords) to MatchType values to be used as arguments." 41 | all) 42 | 43 | (def ^{:added "8.12.4-0" 44 | :tag clojure.lang.PersistentArrayMap} 45 | by-val 46 | "Map of MatchType values to phone number matches (keywords)." 47 | (clojure.set/map-invert all)) 48 | 49 | (def ^{:added "8.12.16-1" 50 | :tag clojure.lang.PersistentArrayMap} 51 | by-val-arg 52 | "Map of MatchType values to phone number matches (keywords) to be used as arguments." 53 | by-val) 54 | 55 | (defn mapper 56 | "Generates a map from PhoneNumberMatch object." 57 | {:added "8.12.4-0" 58 | :tag lazy_map.core.LazyMap} 59 | [^PhoneNumberMatch m] 60 | (let [num (.number m) 61 | num (locking num (if (.hasRawInput num) num (.setRawInput num (.rawString m))))] 62 | (merge 63 | (lazy-map #::{}) 64 | #::{:phone-number/number num 65 | :start (.start m) 66 | :end (.end m) 67 | :raw-string (.rawString m)}))) 68 | -------------------------------------------------------------------------------- /src/phone_number/net_code.clj: -------------------------------------------------------------------------------- 1 | (ns 2 | 3 | ^{:doc "Global network calling codes handling for phone-number." 4 | :author "Paweł Wilk" 5 | :added "8.12.4-0"} 6 | 7 | phone-number.net-code 8 | 9 | (:require [clojure.set] 10 | [phone-number.util :as util]) 11 | 12 | (:import [com.google.i18n.phonenumbers 13 | PhoneNumberUtil 14 | NumberParseException])) 15 | 16 | ;; 17 | ;; Supported Global Network Calling Codes 18 | ;; 19 | 20 | (def ^{:added "8.12.16-1" 21 | :tag clojure.lang.PersistentHashSet} 22 | all 23 | "Set of supported global network calling codes." 24 | (set (.getSupportedGlobalNetworkCallingCodes (util/instance)))) 25 | 26 | (def ^{:added "8.12.4-0" 27 | :tag clojure.lang.PersistentHashSet} 28 | all-arg 29 | "Set of supported global network calling codes (to be used as arguments)." 30 | all) 31 | 32 | (def ^{:added "8.12.16-1" 33 | :tag clojure.lang.PersistentHashSet} 34 | by-val 35 | "Set of supported values of global network calling codes." 36 | all) 37 | 38 | (def ^{:added "8.12.16-1" 39 | :tag clojure.lang.PersistentHashSet} 40 | by-val-arg 41 | "Set of supported values of global network calling codes (to be used as method arguments)." 42 | all-arg) 43 | 44 | (def ^{:added "8.12.4-0" 45 | :tag clojure.lang.PersistentVector} 46 | all-vec 47 | "Vector of all supported global network calling codes." 48 | (vec all)) 49 | 50 | (def ^{:added "8.12.16-1" 51 | :tag clojure.lang.PersistentVector} 52 | by-val-vec 53 | "Vector of all supported global network calling codes." 54 | (vec by-val)) 55 | 56 | (def ^{:added "8.12.16-1" 57 | :tag clojure.lang.PersistentVector} 58 | all-arg-vec 59 | "Vector of all supported global network calling codes (valid as args)." 60 | (vec all-arg)) 61 | 62 | (def ^{:added "8.12.16-1" 63 | :tag clojure.lang.PersistentVector} 64 | by-val-arg-vec 65 | "Vector of all supported global network calling codes (valid as args)." 66 | (vec by-val-arg)) 67 | 68 | (defn valid? 69 | "Returns true if the given region-specification is a valid region code, false 70 | otherwise." 71 | {:added "8.12.4-0" :tag Boolean} 72 | [^Integer calling-code] 73 | (contains? all calling-code)) 74 | 75 | (defn valid-arg? 76 | "Returns true if the given region-specification is a valid region code (to be used as 77 | an argument), false otherwise." 78 | {:added "8.12.16-1" :tag Boolean} 79 | [^Integer calling-code] 80 | (contains? all-arg calling-code)) 81 | 82 | (defn parse 83 | "Parses a network calling code and returns a value that can be supplied to 84 | Libphonenumber methods." 85 | {:added "8.12.4-0" :tag Integer} 86 | ([^Integer calling-code] 87 | (assert (valid-arg? calling-code) 88 | (str "Global network calling code " calling-code " is not valid")) 89 | calling-code)) 90 | 91 | (defn generate-sample 92 | "Generates random global network calling code." 93 | {:added "8.12.4-0" :tag Integer} 94 | ([] (rand-nth all-vec)) 95 | ([^java.util.Random rng] (util/get-rand-nth all-vec rng))) 96 | 97 | (defn generate-sample-val 98 | "Generates random global network calling code." 99 | {:added "8.12.16-1" :tag Integer} 100 | ([] (rand-nth by-val-vec)) 101 | ([^java.util.Random rng] (util/get-rand-nth by-val-vec rng))) 102 | 103 | (defn generate-arg-sample 104 | "Generates random global network calling code." 105 | {:added "8.12.16-1" :tag Integer} 106 | ([] (rand-nth all-arg-vec)) 107 | ([^java.util.Random rng] (util/get-rand-nth all-arg-vec rng))) 108 | 109 | (defn generate-arg-sample-val 110 | "Generates random global network calling code." 111 | {:added "8.12.16-1" :tag Integer} 112 | ([] (rand-nth by-val-arg-vec)) 113 | ([^java.util.Random rng] (util/get-rand-nth by-val-arg-vec rng))) 114 | -------------------------------------------------------------------------------- /src/phone_number/region.clj: -------------------------------------------------------------------------------- 1 | (ns 2 | 3 | ^{:doc "Region handling for phone-number." 4 | :author "Paweł Wilk" 5 | :added "8.12.4-0"} 6 | 7 | phone-number.region 8 | 9 | (:require [clojure.set] 10 | [clojure.string] 11 | [phone-number.util :as util]) 12 | 13 | (:import [com.google.i18n.phonenumbers 14 | PhoneNumberUtil 15 | NumberParseException])) 16 | 17 | ;; 18 | ;; Supported Regions 19 | ;; 20 | 21 | (def ^{:added "8.12.16-1" 22 | :const true 23 | :tag clojure.lang.Keyword} 24 | non-geo ::world) 25 | 26 | (def ^{:added "8.12.16-1" 27 | :const true 28 | :tag String} 29 | non-geo-val "001") 30 | 31 | (def ^{:added "8.12.4-0" 32 | :tag clojure.lang.PersistentHashMap} 33 | all-arg 34 | "Mapping of supported regions (keywords) to region values (strings) suitable to be 35 | used as arguments." 36 | (let [tns (str (ns-name *ns*))] 37 | (into #::{} 38 | (map 39 | (juxt #(keyword tns (clojure.string/lower-case %)) identity) 40 | (.getSupportedRegions (util/instance)))))) 41 | 42 | (def ^{:added "8.12.4-0" 43 | :tag clojure.lang.PersistentHashMap} 44 | all 45 | "Mapping of supported regions (keywords) to region values (strings)." 46 | (assoc all-arg non-geo non-geo-val)) 47 | 48 | (def ^{:added "8.12.4-0" 49 | :tag clojure.lang.PersistentHashMap} 50 | by-val 51 | "Mapping of supported region values (strings) to regions (keywords)." 52 | (clojure.set/map-invert all)) 53 | 54 | (def ^{:added "8.12.4-0" 55 | :tag clojure.lang.PersistentHashMap} 56 | by-val-arg 57 | "Mapping of supported region values (strings) to regions (keywords)." 58 | (clojure.set/map-invert all-arg)) 59 | 60 | (def ^{:added "8.12.4-0" 61 | :const true 62 | :tag clojure.lang.Keyword} 63 | default nil) 64 | 65 | (def ^{:added "8.12.4-0" 66 | :const true 67 | :tag String} 68 | default-val (all default)) 69 | 70 | (def ^{:added "8.12.4-0" 71 | :tag clojure.lang.PersistentVector} 72 | all-vec 73 | "Vector of regions (keywords)." 74 | (vec (keys all))) 75 | 76 | (def ^{:added "8.12.4-0" 77 | :tag clojure.lang.PersistentVector} 78 | all-arg-vec 79 | "Vector of regions (keywords)." 80 | (vec (keys all-arg))) 81 | 82 | (def ^{:added "8.12.4-0" 83 | :tag clojure.lang.PersistentVector} 84 | by-val-vec 85 | "Vector of regions (string values)." 86 | (vec (keys by-val))) 87 | 88 | (def ^{:added "8.12.4-0" 89 | :tag clojure.lang.PersistentVector} 90 | by-val-arg-vec 91 | "Vector of regions (string values)." 92 | (vec (keys by-val-arg))) 93 | 94 | (defn valid? 95 | "Returns `true` if the given region-specification is a valid region code, `false` 96 | otherwise. In its binary form it uses namespace inference." 97 | {:added "8.12.4-0" :tag Boolean} 98 | ([^clojure.lang.Keyword region-specification] 99 | (contains? all region-specification)) 100 | ([^clojure.lang.Keyword region-specification 101 | ^Boolean use-infer] 102 | (contains? all (util/ns-infer "phone-number.region" region-specification use-infer)))) 103 | 104 | (defn valid-arg? 105 | "Returns `true` if the given region-specification is a valid region code, `false` 106 | otherwise. In its binary form it uses namespace inference." 107 | {:added "8.12.4-0" :tag Boolean} 108 | ([^clojure.lang.Keyword region-specification] 109 | (contains? all-arg region-specification)) 110 | ([^clojure.lang.Keyword region-specification 111 | ^Boolean use-infer] 112 | (contains? all-arg (util/ns-infer "phone-number.region" region-specification use-infer)))) 113 | 114 | (defn parse 115 | "Parses a region code and returns a value that can be supplied to Libphonenumber 116 | methods." 117 | {:added "8.12.4-0" :tag String} 118 | ([^clojure.lang.Keyword k] 119 | (parse k true)) 120 | ([^clojure.lang.Keyword k 121 | ^Boolean use-infer] 122 | (if (some? k) 123 | (let [k (util/ns-infer "phone-number.region" k use-infer)] 124 | (assert (valid-arg? k) (str "Region code " k " is not valid")) 125 | (all k))))) 126 | 127 | (defn normalize-arg 128 | "Parses a region code and returns its normalized version that can be used as an 129 | argument." 130 | {:added "8.12.16-1" :tag String} 131 | ([^clojure.lang.Keyword k] 132 | (normalize-arg k true)) 133 | ([^clojure.lang.Keyword k 134 | ^Boolean use-infer] 135 | (if (some? k) 136 | (let [k (util/ns-infer "phone-number.region" k use-infer)] 137 | (assert (valid-arg? k) (str "Region code " k " is not valid")) 138 | k)))) 139 | 140 | (defn normalize 141 | "Parses a region code and returns its normalized version." 142 | {:added "8.12.16-1" :tag String} 143 | ([^clojure.lang.Keyword k] 144 | (normalize k true)) 145 | ([^clojure.lang.Keyword k 146 | ^Boolean use-infer] 147 | (if (some? k) 148 | (let [k (util/ns-infer "phone-number.region" k use-infer)] 149 | (assert (valid? k) (str "Region code " k " is not valid")) 150 | k)))) 151 | 152 | (defn generate-sample 153 | "Generates random region code." 154 | {:added "8.12.4-0" :tag clojure.lang.Keyword} 155 | ([] (rand-nth all-vec)) 156 | ([^java.util.Random rng] (util/get-rand-nth all-vec rng))) 157 | 158 | (defn generate-sample-val 159 | "Generates random region code (string value)." 160 | {:added "8.12.4-0" :tag String} 161 | ([] (rand-nth by-val-vec)) 162 | ([^java.util.Random rng] (util/get-rand-nth by-val-vec rng))) 163 | 164 | (defn generate-arg-sample 165 | "Generates random region code." 166 | {:added "8.12.4-0" :tag clojure.lang.Keyword} 167 | ([] (rand-nth all-arg-vec)) 168 | ([^java.util.Random rng] (util/get-rand-nth all-arg-vec rng))) 169 | 170 | (defn generate-arg-sample-val 171 | "Generates random region code (string value)." 172 | {:added "8.12.4-0" :tag String} 173 | ([] (rand-nth by-val-arg-vec)) 174 | ([^java.util.Random rng] (util/get-rand-nth by-val-arg-vec rng))) 175 | -------------------------------------------------------------------------------- /src/phone_number/sample.clj: -------------------------------------------------------------------------------- 1 | (ns 2 | 3 | ^{:doc "Clojure interface to Libphonenumber, sample." 4 | :author "Paweł Wilk" 5 | :added "8.12.4-2" 6 | :no-doc true} 7 | 8 | phone-number.sample) 9 | 10 | (comment 11 | nil) 12 | -------------------------------------------------------------------------------- /src/phone_number/short.clj: -------------------------------------------------------------------------------- 1 | (ns 2 | 3 | ^{:doc "Clojure interface to Libphonenumber, short numbers." 4 | :author "Paweł Wilk" 5 | :added "8.12.4-2" 6 | :no-doc true} 7 | 8 | phone-number.short) 9 | 10 | (comment 11 | nil) 12 | -------------------------------------------------------------------------------- /src/phone_number/type.clj: -------------------------------------------------------------------------------- 1 | (ns 2 | 3 | ^{:doc "Phone number types for phone-number." 4 | :author "Paweł Wilk" 5 | :added "8.12.4-0"} 6 | 7 | phone-number.type 8 | 9 | (:require [clojure.set] 10 | [phone-number.util :as util]) 11 | 12 | (:import [com.google.i18n.phonenumbers 13 | PhoneNumberUtil 14 | PhoneNumberUtil$PhoneNumberType])) 15 | 16 | (def ^{:added "8.12.4-0" 17 | :tag clojure.lang.PersistentHashMap} 18 | all 19 | "Map of phone number types (keywords) to PhoneNumberType values." 20 | #::{:fixed-line PhoneNumberUtil$PhoneNumberType/FIXED_LINE 21 | :mobile PhoneNumberUtil$PhoneNumberType/MOBILE 22 | :fixed-line-or-mobile PhoneNumberUtil$PhoneNumberType/FIXED_LINE_OR_MOBILE 23 | :toll-free PhoneNumberUtil$PhoneNumberType/TOLL_FREE 24 | :premium-rate PhoneNumberUtil$PhoneNumberType/PREMIUM_RATE 25 | :shared-cost PhoneNumberUtil$PhoneNumberType/SHARED_COST 26 | :voip PhoneNumberUtil$PhoneNumberType/VOIP 27 | :personal PhoneNumberUtil$PhoneNumberType/PERSONAL_NUMBER 28 | :pager PhoneNumberUtil$PhoneNumberType/PAGER 29 | :uan PhoneNumberUtil$PhoneNumberType/UAN 30 | :voicemail PhoneNumberUtil$PhoneNumberType/VOICEMAIL 31 | :unknown PhoneNumberUtil$PhoneNumberType/UNKNOWN}) 32 | 33 | (def ^{:added "8.12.16-1" 34 | :const true 35 | :tag clojure.lang.Keyword} 36 | unknown ::unknown) 37 | 38 | (def ^{:added "8.12.16-1" 39 | :const true 40 | :tag String} 41 | unknown-val (all ::unknown)) 42 | 43 | (def ^{:added "8.12.4-0" 44 | :tag clojure.lang.PersistentHashMap} 45 | all-arg 46 | "Map of PhoneNumberType values to phone number types (keywords) suitable to be 47 | passed as arguments." 48 | (dissoc all unknown)) 49 | 50 | (def ^{:added "8.12.4-0" 51 | :tag clojure.lang.PersistentHashMap} 52 | by-val 53 | "Map of PhoneNumberType values to phone number types (keywords)." 54 | (clojure.set/map-invert all)) 55 | 56 | (def ^{:added "8.12.4-0" 57 | :tag clojure.lang.PersistentHashMap} 58 | by-val-arg 59 | "Map of PhoneNumberType values to phone number types (keywords)." 60 | (clojure.set/map-invert all-arg)) 61 | 62 | (def ^{:added "8.12.4-0" 63 | :const true 64 | :tag clojure.lang.Keyword} 65 | default ::fixed-line) 66 | 67 | (def ^{:added "8.12.4-0" 68 | :tag PhoneNumberUtil$PhoneNumberType} 69 | default-val (all default)) 70 | 71 | (def ^{:added "8.12.4-0" 72 | :tag clojure.lang.PersistentVector} 73 | all-vec 74 | "Vector of types (keywords)." 75 | (vec (keys all))) 76 | 77 | (def ^{:added "8.12.4-0" 78 | :tag clojure.lang.PersistentVector} 79 | all-arg-vec 80 | "Vector of types (keywords)." 81 | (vec (keys all-arg))) 82 | 83 | (def ^{:added "8.12.4-0" 84 | :tag clojure.lang.PersistentVector} 85 | by-val-vec 86 | "Vector of types (PhoneNumberType values)." 87 | (vec (keys by-val))) 88 | 89 | (def ^{:added "8.12.4-0" 90 | :tag clojure.lang.PersistentVector} 91 | by-val-arg-vec 92 | "Vector of types (PhoneNumberType values)." 93 | (vec (keys by-val-arg))) 94 | 95 | (defn valid? 96 | "Returns true if the given number-type is valid, false otherwise. 97 | Use valid-arg? for argument testing when building phone numbers." 98 | {:added "8.12.4-0" :tag Boolean} 99 | ([^clojure.lang.Keyword number-type] 100 | (contains? all number-type)) 101 | ([^clojure.lang.Keyword number-type 102 | ^Boolean use-infer] 103 | (contains? all (util/ns-infer "phone-number.type" number-type use-infer)))) 104 | 105 | (defn valid-arg? 106 | "Returns true if the given number-type is valid, false otherwise. 107 | Excludes unknown type from the valid list." 108 | {:added "8.12.4-0" :tag Boolean} 109 | ([^clojure.lang.Keyword number-type] 110 | (contains? all-arg number-type)) 111 | ([^clojure.lang.Keyword number-type 112 | ^Boolean use-infer] 113 | (contains? all-arg (util/ns-infer "phone-number.type" number-type use-infer)))) 114 | 115 | (defn parse 116 | "Parses a type and returns a value that can be supplied to Libphonenumber methods. If 117 | nil is given it returns the default value." 118 | {:added "8.12.4-0" :tag PhoneNumberUtil$PhoneNumberType} 119 | ([^clojure.lang.Keyword k] 120 | (parse k true)) 121 | ([^clojure.lang.Keyword k 122 | ^Boolean use-infer] 123 | (if (nil? k) 124 | default-val 125 | (let [k (util/ns-infer "phone-number.type" k use-infer)] 126 | (assert (valid-arg? k) (str "Type " k " is not valid")) 127 | (all-arg k))))) 128 | 129 | (defn generate-sample 130 | "Generates random number type." 131 | {:added "8.12.4-0" :tag clojure.lang.Keyword} 132 | ([] (rand-nth all-vec)) 133 | ([^java.util.Random rng] (util/get-rand-nth all-vec rng))) 134 | 135 | (defn generate-sample-val 136 | "Generates random number type (PhoneNumberType value)." 137 | {:added "8.12.4-0" :tag PhoneNumberUtil$PhoneNumberType} 138 | ([] (rand-nth by-val-vec)) 139 | ([^java.util.Random rng] (util/get-rand-nth by-val-vec rng))) 140 | 141 | (defn generate-arg-sample 142 | "Generates random number type suitable to be used as value of an argument." 143 | {:added "8.12.4-0" :tag clojure.lang.Keyword} 144 | ([] (rand-nth all-arg-vec)) 145 | ([^java.util.Random rng] (util/get-rand-nth all-arg-vec rng))) 146 | 147 | (defn generate-arg-sample-val 148 | "Generates random number type (PhoneNumberType value) suitable to be used as value of 149 | an argument." 150 | {:added "8.12.16-1" :tag PhoneNumberUtil$PhoneNumberType} 151 | ([] (rand-nth by-val-arg-vec)) 152 | ([^java.util.Random rng] (util/get-rand-nth by-val-arg-vec rng))) 153 | -------------------------------------------------------------------------------- /src/phone_number/tz_format.clj: -------------------------------------------------------------------------------- 1 | (ns 2 | 3 | ^{:doc "Time zone formats for phone-number." 4 | :author "Paweł Wilk" 5 | :added "8.12.4-0"} 6 | 7 | phone-number.tz-format 8 | 9 | (:refer-clojure :exclude [get]) 10 | 11 | (:require [clojure.set] 12 | [phone-number.util :as util]) 13 | 14 | (:import [java.time.format TextStyle])) 15 | 16 | ;; Time Zone Formats 17 | 18 | (def ^{:added "8.12.4-0" 19 | :tag clojure.lang.PersistentArrayMap} 20 | all 21 | "Map of time zone formats (keywords) to TextStyle objects for time zone formatting." 22 | #::{:id nil 23 | :short TextStyle/SHORT 24 | :narrow TextStyle/NARROW 25 | :full TextStyle/FULL 26 | :short-standalone TextStyle/SHORT_STANDALONE 27 | :narrow-standalone TextStyle/NARROW_STANDALONE 28 | :full-standalone TextStyle/FULL_STANDALONE}) 29 | 30 | (def ^{:added "8.12.4-0" 31 | :const true 32 | :tag clojure.lang.Keyword} 33 | default ::id) 34 | 35 | (def ^{:added "8.12.4-0" 36 | :tag TextStyle} 37 | default-val (all default)) 38 | 39 | (def ^{:added "8.12.16-1" 40 | :tag clojure.lang.PersistentArrayMap} 41 | by-val 42 | "Map of time zone formats to TextStyle objects." 43 | (clojure.set/map-invert all)) 44 | 45 | (def ^{:added "8.12.16-1" 46 | :tag clojure.lang.PersistentArrayMap} 47 | all-arg 48 | "Map of TextStyle objects to time zone formats (keywords) for time zone 49 | formatting (to be used as arguments)." 50 | all) 51 | 52 | (def ^{:added "8.12.16-1" 53 | :tag clojure.lang.PersistentArrayMap} 54 | by-val-arg 55 | "Map of time zone formats as TextStyle objects mapped to keywords (values accepted by 56 | Libphonenumber methods)." 57 | (dissoc by-val default-val)) 58 | 59 | (def ^{:added "8.12.4-0" 60 | :tag clojure.lang.PersistentVector} 61 | all-vec 62 | "Vector of time zone formats (keywords)." 63 | (vec (keys all))) 64 | 65 | (def ^{:added "8.12.16-1" 66 | :tag clojure.lang.PersistentVector} 67 | all-arg-vec 68 | "Vector of time zone formats (keywords) to be used as arguments." 69 | (vec (keys all-arg))) 70 | 71 | (def ^{:added "8.12.16-1" 72 | :tag clojure.lang.PersistentVector} 73 | by-val-vec 74 | "Vector of time zone values." 75 | (vec (keys by-val))) 76 | 77 | (def ^{:added "8.12.16-1" 78 | :tag clojure.lang.PersistentVector} 79 | by-val-arg-vec 80 | "Vector of time zone values suitable to be passed as arguments to methods of 81 | Libphonenumber." 82 | (vec (keys by-val-arg))) 83 | 84 | ;; Time Zone IDs 85 | 86 | (defn valid? 87 | "Returns true if the given tz-format is valid, false otherwise." 88 | {:added "8.12.4-0" :tag Boolean} 89 | ([^clojure.lang.Keyword tz-format] 90 | (contains? all tz-format)) 91 | ([^clojure.lang.Keyword tz-format 92 | ^Boolean use-infer] 93 | (contains? all (util/ns-infer "phone-number.tz-format" tz-format use-infer)))) 94 | 95 | (defn valid-arg? 96 | "Returns true if the given tz-format is valid as an argument, false otherwise." 97 | {:added "8.12.16-1" :tag Boolean} 98 | ([^clojure.lang.Keyword tz-format] 99 | (contains? all-arg tz-format)) 100 | ([^clojure.lang.Keyword tz-format 101 | ^Boolean use-infer] 102 | (contains? all-arg (util/ns-infer "phone-number.tz-format" tz-format use-infer)))) 103 | 104 | (defn transform 105 | "For the given `Locale` object and `TextStyle` object renders a string describing a 106 | time zone identifier (given as a string) passed as the first argument. If the style 107 | is nil then the original object passed as a `zone-id` argument is returned." 108 | {:added "8.12.4-0" 109 | :tag String} 110 | [^String zone-id 111 | ^java.util.Locale l 112 | ^TextStyle style] 113 | (if (or (nil? style) (= default-val style)) 114 | zone-id 115 | (.getDisplayName (java.time.ZoneId/of zone-id) style l))) 116 | 117 | (defn parse 118 | "Parses a time zone format specification and returns a value that can be supplied to 119 | phone-number functions. If nil is given it returns the default value." 120 | {:added "8.12.4-0" :tag TextStyle} 121 | ([^clojure.lang.Keyword k] 122 | (parse k true)) 123 | ([^clojure.lang.Keyword k 124 | ^Boolean use-infer] 125 | (if (nil? k) 126 | default-val 127 | (let [k (util/ns-infer "phone-number.tz-format" k use-infer)] 128 | (assert (valid-arg? k) (str "Time zone format " k " is not valid")) 129 | (all k))))) 130 | -------------------------------------------------------------------------------- /src/phone_number/util.clj: -------------------------------------------------------------------------------- 1 | (ns 2 | 3 | ^{:doc "Singleton wrappers and helpers for phone-number." 4 | :author "Paweł Wilk" 5 | :added "8.12.4-0"} 6 | 7 | phone-number.util 8 | 9 | (:refer-clojure :exclude [short]) 10 | 11 | (:require [trptr.java-wrapper.locale :as l]) 12 | 13 | (:import [com.google.i18n.phonenumbers 14 | PhoneNumberUtil 15 | ShortNumberInfo 16 | geocoding.PhoneNumberOfflineGeocoder 17 | PhoneNumberToCarrierMapper 18 | PhoneNumberToTimeZonesMapper 19 | NumberParseException])) 20 | 21 | ;; Singletons 22 | 23 | (defn instance 24 | {:tag PhoneNumberUtil, :added "8.12.4-0"} 25 | ^PhoneNumberUtil [] 26 | (PhoneNumberUtil/getInstance)) 27 | 28 | (defn short 29 | {:tag ShortNumberInfo, :added "8.12.4-0"} 30 | ^ShortNumberInfo [] 31 | (ShortNumberInfo/getInstance)) 32 | 33 | (defn geo-coder 34 | {:tag PhoneNumberOfflineGeocoder, :added "8.12.4-0"} 35 | ^PhoneNumberOfflineGeocoder [] 36 | (PhoneNumberOfflineGeocoder/getInstance)) 37 | 38 | (defn carrier-mapper 39 | {:tag PhoneNumberToCarrierMapper, :added "8.12.4-0"} 40 | ^PhoneNumberToCarrierMapper [] 41 | (PhoneNumberToCarrierMapper/getInstance)) 42 | 43 | (defn time-zones-mapper 44 | {:tag PhoneNumberToTimeZonesMapper, :added "8.12.4-0"} 45 | ^PhoneNumberToTimeZonesMapper [] 46 | (PhoneNumberToTimeZonesMapper/getInstance)) 47 | 48 | ;; Helpers 49 | 50 | (defmacro try-parse 51 | "Evaluates body and if NumberParseException or NumberFormatException exception is 52 | caught it returns nil." 53 | {:added "8.12.4-0"} 54 | [& body] 55 | `(try ~@body 56 | (catch AssertionError e# nil) 57 | (catch NumberParseException e# nil) 58 | (catch NumberFormatException e# nil))) 59 | 60 | (defmacro try-parse-or-false 61 | "Evaluates body and if NumberParseException or NumberFormatException exception is 62 | caught it returns false." 63 | {:added "8.12.4-0"} 64 | [& body] 65 | `(try (or (do ~@body) false) 66 | (catch AssertionError e# false) 67 | (catch NumberParseException e# false) 68 | (catch NumberFormatException e# false))) 69 | 70 | (defmacro try-null 71 | "Evaluates body and if NullPointerException exception is caught it returns 72 | nil. Otherwise it returns the value of last expression in the body." 73 | {:added "8.12.4-0"} 74 | [& body] 75 | `(try ~@body 76 | (catch NullPointerException e# nil))) 77 | 78 | (defmacro when-not-empty 79 | "Evaluates body when the given value is a non-empty collection." 80 | {:added "8.12.16-1"} 81 | [val & body] 82 | `(when (seq ~val) 83 | ~@body)) 84 | 85 | (defn with-not-empty 86 | "Returns the collection if it's not empty. Otherwise returns `nil`." 87 | {:added "8.12.16-1"} 88 | [obj] 89 | (if (seq obj) obj)) 90 | 91 | (defn count-digits 92 | {:added "8.12.4-1" :tag 'long} 93 | [^long n] 94 | (if (zero? n) 1 95 | (unchecked-inc 96 | (long (Math/floor (Math/log10 n)))))) 97 | 98 | (defn ns-infer 99 | "Takes a string of namespace name and a keyword. If the given keyword is not 100 | namespace-qualified it returns a new keyword with the given namespace added. If the 101 | given keyword is already equipped with a namespace it returns it." 102 | {:added "8.12.4-0" :tag clojure.lang.Keyword} 103 | ([^String ns-name 104 | ^clojure.lang.Keyword k] 105 | (if (simple-keyword? k) 106 | (keyword ns-name (name k)) 107 | k)) 108 | ([^String ns-name 109 | ^clojure.lang.Keyword k 110 | ^Boolean use-infer] 111 | (if use-infer (ns-infer ns-name k) k))) 112 | 113 | (defn inferred-contains? 114 | "Just like the contains? but if the keyword is namespace-qualified it also checks if 115 | the collection contains the same keyword as its key but without a namespace." 116 | {:added "8.12.4-0" :tag Boolean} 117 | [^clojure.lang.IPersistentMap coll 118 | ^clojure.lang.Keyword k] 119 | (or (contains? coll k) 120 | (if (simple-keyword? k) 121 | false 122 | (contains? coll (keyword (name k)))))) 123 | 124 | (defn inferred-get 125 | "Just like the get function but if the keyword is namespace-qualified it first 126 | attempts to look for the value associated with it. If that fails it uses the 127 | variant of the keyword without any namespace." 128 | {:added "8.12.4-0"} 129 | ([^clojure.lang.IPersistentMap coll 130 | ^clojure.lang.Keyword k] 131 | (inferred-get coll k nil)) 132 | ([^clojure.lang.IPersistentMap coll 133 | ^clojure.lang.Keyword k 134 | default] 135 | (if (simple-keyword? k) 136 | (k coll default) 137 | ((if (contains? coll k) k (keyword (name k))) coll default)))) 138 | 139 | (defn fmap-k 140 | "For each key and value of the given map m calls a function passed as the first 141 | argument (passing successive keys during calls to it) and generates a map with 142 | values updated by the results returned by the function. When the third argument is 143 | given it should be a map on which operations are performed instead of using the 144 | original map. This may be helpful when we want to avoid merging the results with 145 | another map." 146 | {:added "8.12.4-0" :tag clojure.lang.IPersistentMap} 147 | ([^clojure.lang.IFn f 148 | ^clojure.lang.IPersistentMap m] 149 | (fmap-k f m m)) 150 | ([^clojure.lang.IFn f 151 | ^clojure.lang.IPersistentMap m 152 | ^clojure.lang.IPersistentMap dst] 153 | (reduce-kv 154 | (fn [^clojure.lang.IPersistentMap mp k v] (assoc mp k (f k))) 155 | dst m))) 156 | 157 | (defn fmap-v 158 | "For each key and value of the given map m calls a function passed as the first 159 | argument (passing successive values during calls to it) and generates a map with 160 | values updated by the results returned by the function. When the third argument is 161 | given it should be a map on which operations are performed instead of using the 162 | original map. This may be helpful when we want to avoid merging the results with 163 | another map." 164 | {:added "8.12.16-1" :tag clojure.lang.IPersistentMap} 165 | ([^clojure.lang.IFn f 166 | ^clojure.lang.IPersistentMap m] 167 | (fmap-v f m m)) 168 | ([^clojure.lang.IFn f 169 | ^clojure.lang.IPersistentMap m 170 | ^clojure.lang.IPersistentMap dst] 171 | (reduce-kv 172 | (fn [^clojure.lang.IPersistentMap mp k v] (assoc mp k (f v))) 173 | dst m))) 174 | 175 | (defn map-of-sets-invert 176 | "Like `clojure.set/map-invert` but for map of sets (as values) to preserve all 177 | possible values (as keys of newly created map)." 178 | {:added "8.12.16-1" :tag clojure.lang.IPersistentMap} 179 | [^clojure.lang.IPersistentMap m] 180 | (reduce (fn [^clojure.lang.IPersistentMap am [k v]] 181 | (assoc am k (conj (am k (hash-set)) v))) 182 | (hash-map) 183 | (for [[k st] m v st] [v k]))) 184 | 185 | (defn remove-empty-vals 186 | "Removes empty values from a map." 187 | {:added "8.12.4-0" :tag clojure.lang.IPersistentMap} 188 | [^clojure.lang.IPersistentMap m] 189 | (reduce-kv 190 | (fn [^clojure.lang.IPersistentMap mp k v] 191 | (if (nil? v) (dissoc mp k) mp)) 192 | m m)) 193 | 194 | (defn- gen-is-sexp 195 | "For the given keyword k and function name f it generates predicate function 196 | definition code that compares the result of calling the function on a phone number 197 | with the keyword. A helper that is used in macros." 198 | {:added "8.12.4-0"} 199 | [^clojure.lang.Keyword k 200 | ^clojure.lang.Symbol f] 201 | (let [fn-name (symbol (str "is-" (name k) "?"))] 202 | (list 'defn fn-name 203 | {:added (:added (meta (var gen-is-sexp))), :tag 'Boolean 204 | :doc (str "Returns true when " (name f) " is " k ", false otherwise.\n")} 205 | (list '[phone-number] 206 | (list fn-name 'phone-number nil)) 207 | (list '[phone-number region-specification] 208 | (list 'util/try-parse-or-false 209 | (list '= k (list f 'phone-number 'region-specification))))))) 210 | 211 | (defmacro gen-is 212 | "For the given keyword k and function name f uses gen-is-sexp to generate predicate 213 | function definitions." 214 | {:added "8.12.4-0"} 215 | [k f] 216 | (gen-is-sexp k f)) 217 | 218 | (defmacro gen-ises 219 | "Takes a collection of keywords (evaluated) and a function expressed as a symbol (not 220 | evaluated) and generates bunch of function definitions using gen-is-sexp." 221 | {:added "8.12.4-0"} 222 | [coll f] 223 | (cons 'do (map #(gen-is-sexp % f) (eval coll)))) 224 | 225 | (defn get-rand-int 226 | "Like rand-int but optionally uses random number generator." 227 | {:added "8.12.4-0"} ; was: :tag 'int 228 | ([^long n] 229 | (if (some? n) 230 | (rand-int n))) 231 | ([^long n 232 | ^java.util.Random rng] 233 | (if (some? n) 234 | (if (nil? rng) 235 | (get-rand-int n) 236 | (if (zero? n) (int n) (.nextInt rng n)))))) 237 | 238 | (defn random-digits-len 239 | "For 0 or 1 it returns its argument. For other positive numbers it returns a random 240 | natural number from 1 to this number (inclusive) in 50% cases. In other 50% cases 241 | it returns its argument." 242 | {:added "8.12.4-0"} ; was: :tag 'long 243 | ([^long x 244 | ^long iteration 245 | ^Boolean shrink-now] 246 | (if (some? x) 247 | (if (zero? x) x 248 | (if-not shrink-now x 249 | (if (zero? iteration) 1 250 | (if (or (< iteration 6) (zero? (rand-int 2))) 251 | (unchecked-inc (rand-int x)) x)))))) 252 | ([^long x 253 | ^long iteration 254 | ^Boolean shrink-now 255 | ^java.util.Random rng] 256 | (if (some? x) 257 | (if (nil? rng) 258 | (random-digits-len x iteration shrink-now) 259 | (if (zero? x) x 260 | (if-not shrink-now x 261 | (if (zero? iteration) 1 262 | (if (or (< iteration 6) (zero? (get-rand-int 2 rng))) 263 | (unchecked-inc (get-rand-int x rng)) x)))))))) 264 | 265 | (defn gen-digits 266 | "Generates the given number of random digits and converts all into a single string. 267 | When the second argument is present it should be an instance of random number 268 | generator used to get the digits." 269 | {:added "8.12.4-0" :tag String} 270 | ([^long num] 271 | (apply str (repeatedly num #(rand-int 10)))) 272 | ([^long num 273 | ^java.util.Random rng] 274 | (if (some? num) 275 | (if (nil? rng) 276 | (gen-digits num) 277 | (apply str (repeatedly num #(.nextInt rng 10))))))) 278 | 279 | (defn get-rand-nth 280 | "Returns a random element of the given vector. When the second argument is present it 281 | should be an instance of random number generator used to get the random position." 282 | {:added "8.12.4-0" :tag clojure.lang.Keyword} 283 | ([^clojure.lang.IPersistentVector v] 284 | (when-not-empty v (rand-nth v))) 285 | ([^clojure.lang.IPersistentVector v 286 | ^java.util.Random rng] 287 | (when-not-empty v 288 | (if (nil? rng) 289 | (rand-nth v) 290 | (nth v (.nextInt rng (count v))))))) 291 | 292 | (defn lazy-iterator-seq 293 | "Returns a lazy sequence as an interface to the given iterable Java object." 294 | {:added "8.12.4-0" :tag clojure.lang.LazySeq} 295 | ([^Iterable coll] 296 | (lazy-iterator-seq coll (.iterator coll))) 297 | ([^Iterable coll ^java.util.Iterator iter] 298 | (lazy-seq 299 | (if (.hasNext iter) 300 | (cons (.next iter) (lazy-iterator-seq coll iter)))))) 301 | 302 | (defn char-ranges->set 303 | "Returns a set of characters defined as a collection of collections with start and 304 | stop character, e.g.: [\\A \\Z][\\0 \\9]" 305 | {:added "8.12.4-1" :tag clojure.lang.PersistentHashSet} 306 | [& ranges] 307 | (set (mapcat #(map char (range (byte (first %)) (inc (byte (second %))))) ranges))) 308 | 309 | (def ^{:added "8.12.16-1" :tag clojure.lang.PersistentHashSet :private true} 310 | all-locales 311 | l/available-locales) 312 | 313 | (def ^{:added "8.12.4-1" :deprecated "8.12.4-3" :tag clojure.lang.PersistentHashSet} 314 | available-locales 315 | "DEPRECATED: Please use `phone-number.locale/by-val-vec`." 316 | all-locales) 317 | 318 | (def ^{:added "8.12.4-1" :deprecated "8.12.4-3" :tag clojure.lang.PersistentVector} 319 | available-locales-vec 320 | "DEPRECATED: Please use `phone-number.locale/by-val-vec`." 321 | (vec all-locales)) 322 | 323 | (defn valid-locale? 324 | "DEPRECATED: Please use `phone-number.locale/valid?`." 325 | {:added "8.12.4-1" :deprecated "8.12.4-3" :tag Boolean} 326 | [^java.util.Locale locale-specification] 327 | (if (nil? locale-specification) true 328 | (try 329 | (contains? all-locales (l/locale locale-specification)) 330 | (catch Throwable e false)))) 331 | -------------------------------------------------------------------------------- /tests.edn: -------------------------------------------------------------------------------- 1 | {:kaocha/tests 2 | [{:kaocha.testable/type :kaocha.type/midje, 3 | :kaocha.testable/id :unit, 4 | :kaocha/source-paths ["src"] 5 | :kaocha/test-paths ["test"]}], 6 | :kaocha/fail-fast? false, 7 | :kaocha/color? true, 8 | :kaocha/plugins [:kaocha.plugin/randomize 9 | :kaocha.plugin/filter 10 | :kaocha.plugin/capture-output 11 | :kaocha.plugin/print-invocations 12 | :kaocha.plugin/profiling 13 | :kaocha.plugin/notifier 14 | :kaocha.plugin.alpha/spec-test-check 15 | :kaocha.plugin/cloverage], 16 | :kaocha/reporter [kaocha.report/documentation], 17 | :kaocha.plugin.capture-output/capture-output? true, 18 | :kaocha.plugin.profiling/count 3, 19 | :kaocha.plugin.randomize/seed 492209631, 20 | :kaocha.plugin.randomize/randomize? true, 21 | :kaocha.plugin.notifier/command "bin/test-notifier %{message} %{title} %{icon} %{failed?}" 22 | :kaocha/bindings {phone-number.core/*default-dialing-region* :phone-number.region/us} 23 | :cloverage/opts {:ns-exclude-regex [], 24 | :text? false, 25 | :lcov? false, 26 | :high-watermark 80, 27 | :fail-threshold 0, 28 | :output "target/coverage", 29 | :low-watermark 50, 30 | :ns-regex [], 31 | :summary? true, 32 | :coveralls? false, 33 | :emma-xml? false, 34 | :html? true, 35 | :nop? false, 36 | :codecov? true}} 37 | --------------------------------------------------------------------------------