Documentation
¶
Overview ¶
Package phonex parses, validates and formats international phone numbers.
The metadata behind it is generated directly from Google's libphonenumber PhoneNumberMetadata.xml, so the number ranges, formatting rules and trunk prefixes are the same ones the reference implementation uses.
Parsing ¶
Parse accepts numbers in international form, in national form when a default region is given, and in RFC 3966 form:
p, err := phonex.Parse("+998 90 123 45 67")
p, err := phonex.Parse("90 123 45 67", phonex.WithDefaultCountry("UZ"))
p, err := phonex.Parse("tel:+1-202-555-0123;ext=42")
Parse enforces only the bounds E.164 sets for any number. It does not judge the number against its own country's rules, so a wrong-length or unassigned number still parses and the checks below are what report on it. Gate on IsValid before trusting a parsed number.
p.IsPossible() // the length is one the numbering plan uses p.IsValid() // the number falls in an assigned range p.Possibility() // why a length check failed
Formatting ¶
p.E164() // +12025550123
p.International() // +1 202-555-0123
p.National() // (202) 555-0123
p.RFC3966() // tel:+1-202-555-0123
p.OutOfCountry("GB") // 00 1 202-555-0123
Formatter formats a number while it is being typed, for use in an input field:
f := phonex.NewFormatter("US")
f.Input("2025550123") // (202) 555-0123
Allocation behaviour ¶
A Phone stores its digits inline, so parsing into an existing value does no allocation at all for numbers in international form. In a hot loop, reuse a Phone and pass options as a struct:
var p phonex.Phone
opts := phonex.DefaultParseOptions()
opts.DefaultCountry = "UZ"
for _, s := range numbers {
if err := p.ParseWith(s, opts); err == nil {
use(p.E164())
}
}
Short numbers ¶
Short numbers such as 112 and 911 are a different problem: they have no international form and the same digits mean different things in different countries. Parse rejects them as too short. They live in the shortnumber subpackage, which keeps its own metadata so that programs which never need it do not link it in:
shortnumber.IsEmergency("112", "GB") // true
shortnumber.ConnectsToEmergency("911123", "US") // true
Where a number is, and whose it is ¶
The geocoding, carrier and timezone subpackages answer questions the core metadata cannot. They key off the number's prefix, so they describe where and how the number was issued, not where its owner is now:
geocoding.Area(p) // "London" timezone.For(p) // ["Europe/London"] carrier.SafeDisplayName(p) // "" where number portability makes it unreliable
Each carries its own data and is a separate package so that a program which does not need it does not link it in: geocoding alone is several megabytes.
Regenerating the metadata ¶
countries/generated.go is produced by cmd/phonexgen from the vendored upstream XML, pinned to a tagged libphonenumber release. Refresh it with:
go generate ./...
The difftest module compares this package against libphonenumber itself over the whole metadata; see difftest/ and "make diff".
Index ¶
- Constants
- Variables
- func Equal(a, b string, opts ...ParseOption) bool
- func Fingerprint(p *Phone, opts ...HashOption) string
- func IsPossible(input string, opts ...ParseOption) bool
- func IsValid(input string, opts ...ParseOption) bool
- func Normalize(input string) string
- func NormalizeBytes(input []byte) []byte
- func Redact(p *Phone) string
- func SortNumbers(numbers []string, opts ...ParseOption) []string
- func SupportedRegions() []string
- func ToE164(input string, opts ...ParseOption) (string, error)
- func Unique(numbers []string, opts ...ParseOption) []string
- type CountryCodeSource
- type ErrorCode
- type FormatType
- type Formatter
- type HashAlgorithm
- type HashOption
- type HashOptions
- type MaskOptions
- type MatchType
- type Metadata
- func Countries() []*Metadata
- func Country(iso2 string) (*Metadata, bool)
- func CountryByDialCode(code string) (*Metadata, bool)
- func CountryByPhone(number string, opts ...ParseOption) (*Metadata, bool)
- func NonGeoEntities() []*Metadata
- func RegionsForDialCode(code string) []*Metadata
- func SearchCountries(query string) []*Metadata
- type ParseOption
- type ParseOptions
- type Phone
- func ExampleNumber(region string) (*Phone, bool)
- func ExampleNumberForType(region string, t PhoneType) (*Phone, bool)
- func Generate(region string) (*Phone, bool)
- func GenerateForPrefix(region, prefix string, intn func(n int) int) (*Phone, bool)
- func GenerateForType(region string, t PhoneType) (*Phone, bool)
- func GenerateWith(region string, t PhoneType, intn func(n int) int) (*Phone, bool)
- func Parse(input string, opts ...ParseOption) (*Phone, error)
- func ParseBytes(input []byte, opts ...ParseOption) (*Phone, error)
- func ParseWith(input string, options ParseOptions) (*Phone, error)
- func (p *Phone) AppendE164(dst []byte) []byte
- func (p *Phone) CanBeInternationallyDialled() bool
- func (p *Phone) CarrierCode() string
- func (p *Phone) Clone() *Phone
- func (p *Phone) Country() string
- func (p *Phone) CountryCode() string
- func (p *Phone) CountryName() string
- func (p *Phone) DialCode() string
- func (p *Phone) Digits() string
- func (p *Phone) E164() string
- func (p *Phone) Equal(other *Phone) bool
- func (p *Phone) EqualExact(other *Phone) bool
- func (p *Phone) Extension() string
- func (p *Phone) Format(f FormatType) string
- func (p *Phone) HasExtension() bool
- func (p *Phone) Hash(algo ...HashAlgorithm) string
- func (p *Phone) ISO2() string
- func (p *Phone) ISO3() string
- func (p *Phone) International() string
- func (p *Phone) IsFixedLineOrMobile() bool
- func (p *Phone) IsLandline() bool
- func (p *Phone) IsMobile() bool
- func (p *Phone) IsNonGeographical() bool
- func (p *Phone) IsPager() bool
- func (p *Phone) IsPersonalNumber() bool
- func (p *Phone) IsPossible() bool
- func (p *Phone) IsPremiumRate() bool
- func (p *Phone) IsSharedCost() bool
- func (p *Phone) IsTollFree() bool
- func (p *Phone) IsUAN() bool
- func (p *Phone) IsValid() bool
- func (p *Phone) IsValidForRegion(region string) bool
- func (p *Phone) IsVoIP() bool
- func (p *Phone) IsVoicemail() bool
- func (p *Phone) MarshalJSON() ([]byte, error)
- func (p *Phone) MarshalText() ([]byte, error)
- func (p *Phone) Mask(opts ...MaskOptions) string
- func (p *Phone) Match(other *Phone) MatchType
- func (p *Phone) Metadata() *Metadata
- func (p *Phone) MobileNumberPortable() bool
- func (p *Phone) NSN() string
- func (p *Phone) National() string
- func (p *Phone) NationalDigits() string
- func (p *Phone) NationalWithCarrier(carrierCode string) string
- func (p *Phone) OutOfCountry(fromRegion string) string
- func (p *Phone) Parse(input string, opts ...ParseOption) error
- func (p *Phone) ParseBytes(input []byte, opts ...ParseOption) error
- func (p *Phone) ParseWith(input string, options ParseOptions) error
- func (p *Phone) Possibility() Possibility
- func (p *Phone) PossibilityForType(t PhoneType) Possibility
- func (p *Phone) RFC3966() string
- func (p *Phone) RawInput() string
- func (p *Phone) Scan(value any) error
- func (p *Phone) Source() CountryCodeSource
- func (p *Phone) String() string
- func (p *Phone) Timezones() []string
- func (p *Phone) Type() PhoneType
- func (p *Phone) UnmarshalJSON(data []byte) error
- func (p *Phone) UnmarshalText(text []byte) error
- func (p Phone) Value() (driver.Value, error)
- type PhoneType
- type Possibility
- type Result
- type ValidationError
Examples ¶
Constants ¶
const ( FixedLine = countries.FixedLine Mobile = countries.Mobile TollFree = countries.TollFree PremiumRate = countries.PremiumRate VoIP = countries.VoIP PersonalNumber = countries.PersonalNumber Pager = countries.Pager UAN = countries.UAN Voicemail = countries.Voicemail FixedLineOrMobile = countries.FixedLineOrMobile Unknown = countries.Unknown )
Number ranges, mirroring libphonenumber's PhoneNumberType.
const AnyType = Unknown
AnyType asks for a number of whatever range the region defines, preferring mobile. It is the type Generate uses.
It shares a value with Unknown, which Type reports when no range matches: both mean "no particular range", read from opposite ends. Passing a Type() result straight back into GenerateWith therefore asks for any type rather than failing, which is the harmless reading of the two.
Variables ¶
var ( ErrInvalidCharacters = &ValidationError{Code: CodeInvalidCharacters, Message: "invalid characters"} ErrTooShort = &ValidationError{Code: CodeTooShort, Message: "too short"} ErrTooLong = &ValidationError{Code: CodeTooLong, Message: "too long"} ErrInvalidCountry = &ValidationError{Code: CodeInvalidCountry, Message: "invalid country"} ErrInvalidCountryCode = &ValidationError{Code: CodeInvalidCountryCode, Message: "invalid country code"} ErrInvalidPrefix = &ValidationError{Code: CodeInvalidPrefix, Message: "invalid prefix"} ErrInvalidFormat = &ValidationError{Code: CodeInvalidFormat, Message: "invalid format"} ErrInvalidType = &ValidationError{Code: CodeInvalidType, Message: "invalid type"} ErrMissingCountry = &ValidationError{Code: CodeMissingCountry, Message: "missing country"} ErrInvalidExtension = &ValidationError{Code: CodeInvalidExtension, Message: "invalid extension"} // ErrInvalidLength reports a digit count that falls between two lengths // the region allows, so the number is neither too short nor too long. ErrInvalidLength = &ValidationError{Code: CodeInvalidLength, Message: "invalid length for region"} )
var ( MaskLast4 = MaskOptions{Prefix: 0, Suffix: 4, Mask: "*"} // masks everything except last 4 MaskFirst3 = MaskOptions{Prefix: 3, Suffix: 0, Mask: "*"} // masks everything except first 3 MaskMiddle = MaskOptions{Prefix: 4, Suffix: 2, Mask: "*"} // e.g. +99890****67 MaskFull = MaskOptions{Prefix: 0, Suffix: 0, Mask: "*"} )
Functions ¶
func Equal ¶
func Equal(a, b string, opts ...ParseOption) bool
Equal parses both inputs and reports whether they are the same number.
func Fingerprint ¶
func Fingerprint(p *Phone, opts ...HashOption) string
Fingerprint returns a stable hash of the phone number. If WithSecret is provided, it uses HMAC-SHA256, otherwise it uses standard SHA256.
func IsPossible ¶
func IsPossible(input string, opts ...ParseOption) bool
IsPossible parses input and reports whether its length is plausible.
func IsValid ¶
func IsValid(input string, opts ...ParseOption) bool
IsValid parses input and reports whether it is a valid number.
func Normalize ¶
Normalize strips punctuation and spacing from input, keeping the digits and a leading '+'. It does not parse or validate: use E164 for a canonical number, and this for cheap cleanup of an input field.
func NormalizeBytes ¶
NormalizeBytes is Normalize for a byte slice. The result is a fresh slice.
func SortNumbers ¶
func SortNumbers(numbers []string, opts ...ParseOption) []string
SortNumbers returns the E.164 form of each input in ascending order. Sorting the canonical form groups numbers by calling code, which is what makes the result useful for display. Inputs that fail to parse are skipped.
func SupportedRegions ¶
func SupportedRegions() []string
SupportedRegions returns every ISO-3166 alpha-2 code with metadata, sorted.
func ToE164 ¶
func ToE164(input string, opts ...ParseOption) (string, error)
ToE164 parses input and returns its canonical E.164 form, or an error if it cannot be parsed. It is the one-call form of Parse followed by E164.
func Unique ¶
func Unique(numbers []string, opts ...ParseOption) []string
Unique returns the E.164 form of each distinct number, in the order it was first seen. Inputs that fail to parse are skipped.
Types ¶
type CountryCodeSource ¶
type CountryCodeSource uint8
CountryCodeSource records how the calling code was determined while parsing.
const ( // FromDefaultCountry means the number carried no calling code and the // default region supplied it. FromDefaultCountry CountryCodeSource = iota // FromNumberWithPlusSign means the number started with '+'. FromNumberWithPlusSign // FromNumberWithIDD means the number started with the default region's // international dialling prefix, e.g. "00" or "011". FromNumberWithIDD // FromNumberWithoutPlusSign means the number started with the calling // code but no '+' and no IDD. FromNumberWithoutPlusSign )
func (CountryCodeSource) String ¶
func (s CountryCodeSource) String() string
type FormatType ¶
type FormatType int
FormatType selects an output format.
const ( // FormatE164 is the canonical machine format, e.g. "+998901234567". FormatE164 FormatType = iota // FormatInternational is the human-readable international format, // e.g. "+998 90 123 45 67". FormatInternational // FormatNational is the format used inside the country, including the // trunk prefix, e.g. "(202) 555-0123" or "090 123 45 67". FormatNational // FormatRFC3966 is the "tel:" URI form, e.g. "tel:+998-90-123-45-67". FormatRFC3966 )
type Formatter ¶
type Formatter struct {
// contains filtered or unexported fields
}
Formatter formats a number while it is being typed, one digit at a time.
It is the counterpart of libphonenumber's AsYouTypeFormatter and is meant to drive an input field:
f := phonex.NewFormatter("US")
for _, r := range "2025550123" {
out = f.InputDigit(r)
}
// out == "(202) 555-0123"
A Formatter is not safe for concurrent use.
func NewFormatter ¶
NewFormatter returns a Formatter for numbers typed in region. An unknown region still yields a usable Formatter: it formats numbers typed in international form and echoes anything else.
Example ¶
package main
import (
"fmt"
"github.com/bakhod1r/phonex"
)
func main() {
f := phonex.NewFormatter("US")
for _, r := range "2025550123" {
fmt.Println(f.InputDigit(r))
}
}
Output: 2 20 202 202-5 202-55 202-555 202-5550 (202) 555-01 (202) 555-012 (202) 555-0123
func (*Formatter) Clear ¶
func (f *Formatter) Clear()
Clear resets the Formatter so it can format another number.
func (*Formatter) InputDigit ¶
InputDigit appends one typed character and returns the number formatted so far. Characters other than digits and a leading '+' are ignored.
func (*Formatter) RemoveLastDigit ¶
RemoveLastDigit removes the most recently typed character and returns the number formatted so far.
type HashOption ¶
type HashOption func(*HashOptions)
func WithSecret ¶
func WithSecret(s string) HashOption
type HashOptions ¶
type HashOptions struct {
Secret string
}
type MaskOptions ¶
type MatchType ¶
type MatchType uint8
MatchType grades how closely two numbers correspond.
const ( // NoMatch means the numbers cannot be the same. NoMatch MatchType = iota // ShortNSNMatch means one national number is a suffix of the other, but // neither carries enough context to be sure. ShortNSNMatch // NSNMatch means the national numbers are equal but the calling codes // could not both be confirmed. NSNMatch // ExactMatch means calling code, national number and extension all agree. ExactMatch )
func MatchNumbers ¶
func MatchNumbers(a, b string, opts ...ParseOption) MatchType
MatchNumbers parses both inputs and grades how closely they correspond. Inputs that fail to parse yield NoMatch.
Example ¶
package main
import (
"fmt"
"github.com/bakhod1r/phonex"
)
func main() {
// The same number written nationally and internationally.
fmt.Println(phonex.MatchNumbers("901234567", "+998901234567", phonex.WithDefaultCountry("UZ")))
fmt.Println(phonex.MatchNumbers("+998901234567", "+998901234568"))
}
Output: EXACT_MATCH NO_MATCH
type Metadata ¶
Metadata describes one calling region. It is always handled through a pointer: it carries lazily compiled patterns and must not be copied.
func Countries ¶
func Countries() []*Metadata
Countries returns the metadata of every region, ordered by ISO-3166 alpha-2 code. Non-geographical ranges are not included; see NonGeoEntities.
func CountryByDialCode ¶
CountryByDialCode returns the main region for a calling code. The code may be given with or without a leading '+'. Regions sharing a code (such as the many behind "+1") resolve to the main one; use RegionsForDialCode for all of them.
func CountryByPhone ¶
func CountryByPhone(number string, opts ...ParseOption) (*Metadata, bool)
CountryByPhone parses a number and returns the metadata of its region.
func NonGeoEntities ¶
func NonGeoEntities() []*Metadata
NonGeoEntities returns the metadata of the non-geographical ranges such as +800 (universal freephone), ordered by calling code.
func RegionsForDialCode ¶
RegionsForDialCode returns every region sharing a calling code, main region first. The returned slice must not be modified.
func SearchCountries ¶
SearchCountries returns the regions whose name or ISO code matches query, ordered by ISO-3166 alpha-2 code. Matching is case-insensitive: an exact alpha-2 or alpha-3 code matches that region alone, otherwise the query is matched as a substring of the country name.
type ParseOption ¶
type ParseOption func(ParseOptions) ParseOptions
ParseOption customises parsing. Options take and return the option struct by value so that applying them never forces it onto the heap, which is what keeps Parse allocation-free.
func WithAlphaCharacters ¶
func WithAlphaCharacters() ParseOption
WithAlphaCharacters enables vanity-number parsing, mapping letters to the digits they share a telephone key with.
func WithDefaultCountry ¶
func WithDefaultCountry(region string) ParseOption
WithDefaultCountry sets the region assumed for numbers written without a calling code, e.g. "90 123 45 67" with "UZ".
Example ¶
package main
import (
"fmt"
"github.com/bakhod1r/phonex"
)
func main() {
p, err := phonex.Parse("(202) 555-0123", phonex.WithDefaultCountry("US"))
if err != nil {
panic(err)
}
fmt.Println(p.E164())
}
Output: +12025550123
func WithoutRawInput ¶
func WithoutRawInput() ParseOption
WithoutRawInput drops the original input from the parsed number.
type ParseOptions ¶
type ParseOptions struct {
// DefaultCountry is the ISO-3166 alpha-2 region assumed when the input
// carries no calling code.
DefaultCountry string
// AllowAlpha maps vanity letters onto their keypad digits, so that
// "1-800-FLOWERS" parses as "+18003569377".
AllowAlpha bool
// KeepRawInput retains the original string on the parsed number. It is
// on by default; turning it off lets a Phone outlive a large input
// buffer without pinning it.
KeepRawInput bool
}
ParseOptions configures parsing. Build one with the With* options.
func DefaultParseOptions ¶
func DefaultParseOptions() ParseOptions
DefaultParseOptions is the configuration Parse uses when given no options.
type Phone ¶
type Phone struct {
// contains filtered or unexported fields
}
Phone is a parsed phone number.
A Phone stores its digits inline, so parsing into an existing value does not allocate. The zero value is not a usable number; obtain one from Parse or (*Phone).Parse.
A Phone is not safe for concurrent modification, but a Phone that is no longer being parsed into may be read from several goroutines.
func ExampleNumber ¶
ExampleNumber returns a valid example number for a region, or nil if the metadata carries none. Examples come from libphonenumber and are safe to use in documentation and tests.
func ExampleNumberForType ¶
ExampleNumberForType returns a valid example number of a given range, or nil when the region does not define that range.
func Generate ¶
Generate returns a random valid number for a region, preferring a mobile number. It reports false when the region is unknown or its metadata carries no example to build on.
Generated numbers are for tests and demos. They are valid in the sense that IsValid accepts them, which means they may well belong to a real subscriber — never dial or message them.
func GenerateForPrefix ¶ added in v0.2.0
GenerateForPrefix returns a valid number for the region whose national number starts with the given digits — an area or operator code, such as "20" for London or "416" for Toronto.
The caller knows the code but not the shape around it: the national number's length varies within a country (London's 20 takes eight more digits where most UK codes take seven), and some plans count the trunk digit as part of the national number, so Rome is "06" here and 6 in an atlas. Both are resolved here, so the prefix may be written either way. It reports false when no shape the plan defines accepts the prefix.
intn supplies the randomness, as in GenerateWith; a nil intn uses the global source.
See Generate for the warning that applies to the result.
func GenerateForType ¶
GenerateForType returns a random valid number of a given range. It reports false when the region does not define that range.
Where a country does not separate its fixed-line and mobile ranges, asking for either returns a number the metadata calls FixedLineOrMobile, since that is as precise as the plan gets.
See Generate for the warning that applies to the result.
func GenerateWith ¶ added in v0.2.0
GenerateWith is Generate with the randomness supplied by the caller: intn must return a value in [0,n). A program that has to reproduce its output from a seed cannot use the global math/rand that Generate draws from.
r := rand.New(rand.NewSource(1))
p, ok := phonex.GenerateWith("GB", phonex.Mobile, r.Intn)
Pass AnyType for t to accept any range the region defines, which is what Generate does. A nil intn falls back to the global source.
See Generate for the warning that applies to the result.
func Parse ¶
func Parse(input string, opts ...ParseOption) (*Phone, error)
Parse parses a phone number.
The input may be in international form ("+998901234567", "00998901234567"), in national form when a default country is given, or in RFC 3966 form ("tel:+1-202-555-0123;ext=42"). Punctuation and spacing are ignored.
Parse fails when no region can be determined, when the input holds characters a number cannot, or when the digit count is outside the bounds E.164 sets for any number. It deliberately does not judge the number against its own country's rules: a wrong-length or unassigned number still parses, and Possibility and IsValid are what report on it.
Callers that only want numbers they can dial should check IsValid.
Example ¶
package main
import (
"fmt"
"github.com/bakhod1r/phonex"
)
func main() {
p, err := phonex.Parse("+998 90 123 45 67")
if err != nil {
panic(err)
}
fmt.Println(p.E164(), p.Country(), p.Type(), p.IsValid())
}
Output: +998901234567 UZ MOBILE true
func ParseBytes ¶
func ParseBytes(input []byte, opts ...ParseOption) (*Phone, error)
ParseBytes parses a phone number held in a byte slice. The slice is not retained unless raw input is kept.
func ParseWith ¶
func ParseWith(input string, options ParseOptions) (*Phone, error)
ParseWith parses a phone number using an explicit option struct.
func (*Phone) AppendE164 ¶
AppendE164 appends the E.164 form to dst without allocating.
func (*Phone) CanBeInternationallyDialled ¶
CanBeInternationallyDialled reports whether the number is reachable from outside its own country. Some ranges, such as short service numbers, are domestic only.
func (*Phone) CarrierCode ¶
CarrierCode returns the domestic carrier selection code stripped while parsing, or "" if there was none.
func (*Phone) Country ¶
Country returns the ISO-3166 alpha-2 region code, or "001" for numbers in a non-geographical range such as +800.
func (*Phone) CountryCode ¶
CountryCode returns the calling code with a leading '+'.
func (*Phone) CountryName ¶
CountryName returns the English region name.
func (*Phone) Digits ¶
Digits returns every significant digit: the calling code followed by the national significant number, with no '+'.
func (*Phone) E164 ¶
E164 returns the number in E.164 format. Extensions are not part of E.164 and are omitted.
func (*Phone) EqualExact ¶
EqualExact reports whether two numbers are equal and were written identically. Use it only when the original spelling is itself significant.
func (*Phone) Format ¶
func (p *Phone) Format(f FormatType) string
Format renders the number in the requested format.
Example ¶
package main
import (
"fmt"
"github.com/bakhod1r/phonex"
)
func main() {
p, _ := phonex.Parse("+442070313000")
fmt.Println(p.E164())
fmt.Println(p.International())
fmt.Println(p.National())
fmt.Println(p.RFC3966())
fmt.Println(p.OutOfCountry("US"))
}
Output: +442070313000 +44 20 7031 3000 020 7031 3000 tel:+44-20-7031-3000 011 44 20 7031 3000
func (*Phone) HasExtension ¶
HasExtension reports whether an extension was parsed.
func (*Phone) Hash ¶
func (p *Phone) Hash(algo ...HashAlgorithm) string
Hash returns a hash of the phone number.
func (*Phone) International ¶
International returns the number grouped for international display, e.g. "+44 20 7031 3000".
func (*Phone) IsFixedLineOrMobile ¶
IsFixedLineOrMobile reports whether the number falls in a range the region uses for both fixed-line and mobile numbers.
func (*Phone) IsLandline ¶
IsLandline reports whether the number is a fixed-line number.
func (*Phone) IsMobile ¶
IsMobile reports whether the number is a mobile number. Numbers in regions that do not separate mobile from fixed-line ranges report false; use Type when that distinction matters.
func (*Phone) IsNonGeographical ¶
IsNonGeographical reports whether the number belongs to a global range such as +800 (universal freephone) rather than to a country.
func (*Phone) IsPersonalNumber ¶
IsPersonalNumber reports whether the number is a personal ("follow me") number.
func (*Phone) IsPossible ¶
IsPossible reports whether the number's length is one the region uses, including lengths that only work when dialled locally. A number can be possible without being valid: "+1 555 555 5555" has the right shape for the US but is not an assigned range.
Use Possibility to tell a full number from a local-only one.
func (*Phone) IsPremiumRate ¶
IsPremiumRate reports whether calls to the number are charged at a premium.
func (*Phone) IsSharedCost ¶
IsSharedCost reports whether the cost of calls is shared with the callee.
func (*Phone) IsTollFree ¶
IsTollFree reports whether calls to the number are free to the caller.
func (*Phone) IsValid ¶
IsValid reports whether the number matches one of its region's number ranges. This is the check to use before storing or dialling a number.
Example ¶
package main
import (
"fmt"
"github.com/bakhod1r/phonex"
)
func main() {
// A number can have a plausible shape without being an assigned number.
possible, _ := phonex.Parse("+1 000 000 0000")
fmt.Println(possible.IsPossible(), possible.IsValid())
}
Output: true false
func (*Phone) IsValidForRegion ¶
IsValidForRegion reports whether the number is valid and belongs to the given region. Use it when a number must come from one specific country rather than from anywhere sharing its calling code.
func (*Phone) IsVoicemail ¶
IsVoicemail reports whether the number reaches a voicemail service.
func (*Phone) MarshalJSON ¶
MarshalJSON encodes the number as its E.164 string.
func (*Phone) MarshalText ¶
MarshalText encodes the number as its E.164 string, which makes Phone usable as a map key in encoding/json and as a value in any text-based encoder.
func (*Phone) Mask ¶
func (p *Phone) Mask(opts ...MaskOptions) string
func (*Phone) Match ¶
Match grades how closely two numbers correspond, in the spirit of libphonenumber's isNumberMatch. It is the comparison to use when one side is written in national form and the other in international form.
func (*Phone) Metadata ¶
Metadata returns the region metadata backing this number. The caller must not modify it.
func (*Phone) MobileNumberPortable ¶
MobileNumberPortable reports whether the region supports number portability, meaning the range a number falls into does not reliably identify its carrier.
func (*Phone) NSN ¶
NSN returns the national significant number: the digits after the calling code, with the national (trunk) prefix removed.
func (*Phone) National ¶
National returns the number as it is written inside its own country, e.g. "020 7031 3000".
func (*Phone) NationalDigits ¶
NationalDigits is an alias for NSN.
func (*Phone) NationalWithCarrier ¶
NationalWithCarrier returns the national format with a carrier selection code applied, falling back to the plain national format in regions that do not use one.
func (*Phone) OutOfCountry ¶
OutOfCountry returns the number as it must be dialled from fromRegion, including that region's international dialling prefix. Dialling from the same country yields the national format.
func (*Phone) Parse ¶
func (p *Phone) Parse(input string, opts ...ParseOption) error
Parse parses into the receiver, reusing its storage. Parsing into an existing Phone performs no allocation for numbers in international or plain national form.
func (*Phone) ParseBytes ¶
func (p *Phone) ParseBytes(input []byte, opts ...ParseOption) error
ParseBytes parses into the receiver, reusing its storage.
func (*Phone) ParseWith ¶
func (p *Phone) ParseWith(input string, options ParseOptions) error
ParseWith parses into the receiver using an explicit option struct. It is the form to reach for in hot loops, where building the variadic option slice would itself cost an allocation.
Example ¶
package main
import (
"fmt"
"github.com/bakhod1r/phonex"
)
func main() {
// Reusing a Phone and an option struct keeps a hot loop allocation-free.
var p phonex.Phone
opts := phonex.DefaultParseOptions()
opts.DefaultCountry = "GB"
opts.KeepRawInput = false
for _, s := range []string{"020 7031 3000", "07400 123456"} {
if err := p.ParseWith(s, opts); err != nil {
continue
}
fmt.Println(p.E164(), p.Type())
}
}
Output: +442070313000 FIXED_LINE +447400123456 MOBILE
func (*Phone) Possibility ¶
func (p *Phone) Possibility() Possibility
Possibility reports whether the number has a plausible length, without checking it against the detailed range patterns. It is the cheap check: it never compiles a pattern.
Lengths are judged against the region that owns the calling code rather than the specific region the number resolves to, because a length is a property of the numbering plan as a whole. A Curaçao-length number written with a Bonaire prefix is therefore possible but not valid.
func (*Phone) PossibilityForType ¶
func (p *Phone) PossibilityForType(t PhoneType) Possibility
PossibilityForType is Possibility restricted to one range.
func (*Phone) Scan ¶
Scan reads a number from a database column holding text. A NULL column leaves the Phone untouched.
func (*Phone) Source ¶
func (p *Phone) Source() CountryCodeSource
Source reports how the calling code was determined.
func (*Phone) String ¶
String returns the number in E.164 format, with any extension appended in RFC 3966 style. It is meant for logs and tests, not for display to users; use Format for that.
func (*Phone) Timezones ¶
Timezones returns the IANA time zones of the region. The result must not be modified.
The bundled metadata carries no time zones, so this currently returns nil for every region: libphonenumber does not publish them, and the prefix level data set that would is not vendored here. The accessor exists so that filling internal/metadata/metadata.json is all it takes to enable it.
func (*Phone) Type ¶
Type returns the range this number falls into. The result is computed on first use and cached.
func (*Phone) UnmarshalJSON ¶
UnmarshalJSON parses a JSON string into the number. Anything that does not parse is rejected, so a Phone field can never hold an invalid value.
func (*Phone) UnmarshalText ¶
UnmarshalText parses the number from its text form.
type Possibility ¶
type Possibility uint8
Possibility is the outcome of a length-only check. It distinguishes the reasons a number cannot be valid, which callers use to write precise error messages without re-deriving them.
const ( // IsPossibleNumber means the length is valid for the region. IsPossibleNumber Possibility = iota // IsPossibleLocalOnly means the length is only valid when dialled from // inside the same local area. IsPossibleLocalOnly // InvalidCountryCode means no region uses the calling code. InvalidCountryCode // TooShort means the number has fewer digits than any valid length. TooShort // InvalidLength means the digit count falls between two valid lengths. InvalidLength // TooLong means the number has more digits than any valid length. TooLong )
func (Possibility) String ¶
func (p Possibility) String() string
type Result ¶
Result pairs a parsed number with the error that parsing it produced. Exactly one of the two fields is set.
func ParseMany ¶
func ParseMany(numbers []string, opts ...ParseOption) []Result
ParseMany parses each input, returning one Result per input in the same order. Inputs that fail to parse do not stop the others.
type ValidationError ¶
func (*ValidationError) Error ¶
func (e *ValidationError) Error() string
func (*ValidationError) Is ¶
func (e *ValidationError) Is(target error) bool
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package carrier reports the network a phone number was issued on.
|
Package carrier reports the network a phone number was issued on. |
|
cmd
|
|
|
phonexgen
command
Command phonexgen generates countries/generated.go from Google's libphonenumber PhoneNumberMetadata.xml.
|
Command phonexgen generates countries/generated.go from Google's libphonenumber PhoneNumberMetadata.xml. |
|
Package countries holds the phone-number metadata generated from Google's libphonenumber PhoneNumberMetadata.xml.
|
Package countries holds the phone-number metadata generated from Google's libphonenumber PhoneNumberMetadata.xml. |
|
Package geocoding reports the area a phone number was issued in.
|
Package geocoding reports the area a phone number was issued in. |
|
internal
|
|
|
lazyre
Package lazyre provides a regular expression that is compiled on first use.
|
Package lazyre provides a regular expression that is compiled on first use. |
|
prefixmap
Package prefixmap looks up the longest number prefix that a data set knows about.
|
Package prefixmap looks up the longest number prefix that a data set knows about. |
|
Package shortnumber answers questions about short numbers: the three- to six-digit codes such as 112, 911 or 10086 that only work inside one country and carry no calling code.
|
Package shortnumber answers questions about short numbers: the three- to six-digit codes such as 112, 911 or 10086 that only work inside one country and carry no calling code. |
|
Package timezone reports the IANA time zones a phone number reaches.
|
Package timezone reports the IANA time zones a phone number reaches. |