-
Notifications
You must be signed in to change notification settings - Fork 0
/
cpf.go
78 lines (66 loc) · 1.32 KB
/
cpf.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package br
import "errors"
// IsCPF returns true if cpf is a valid CPF.
func IsCPF(cpf string) bool {
_, err := CanonicalCPF(cpf)
return err == nil
}
var errInvalidCPF = errors.New("invalid CPF")
// CanonicalCPF verifies if a CPF is valid and returns
// the canonical CPF form (without "." or "-") or error.
func CanonicalCPF(cpf string) (string, error) {
cpf = removeNotDigits(cpf)
if !isValidCPF(cpf) {
return "", errInvalidCPF
}
return cpf, nil
}
func isValidCPF(cpf string) bool {
if len(cpf) != 11 {
return false
}
for _, d := range cpf {
if !isDigit(d) {
return false
}
}
if isAllEqual(cpf) {
return false
}
if hashDigit(cpf, 9) != cpf[9] || hashDigit(cpf, 10) != cpf[10] {
return false
}
return true
}
func removeNotDigits(cpf string) string {
if len(cpf) == 14 && cpf[3] == '.' && cpf[7] == '.' && cpf[11] == '-' {
return cpf[:3] + cpf[4:7] + cpf[8:11] + cpf[12:]
}
return cpf
}
func isDigit(r rune) bool {
return '0' <= r && r <= '9'
}
func isAllEqual(cpf string) bool {
first := cpf[0]
for i := range cpf {
if cpf[i] != first {
return false
}
}
return true
}
func hashDigit(cpf string, n int) byte {
var sum int
mul := n + 1
for i := 0; i < n; i++ {
v := int(cpf[i] - '0')
sum += v * mul
mul--
}
rem := sum % 11
if rem < 2 {
return '0'
}
return byte(11-rem) + '0'
}