🇧🇷 CPF validation in Go
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Code review.

+41 -72
+31 -45
cpf.go
··· 7 7 "strings" 8 8 ) 9 9 10 + func checksum(ds []int64) int64 { 11 + var s int64 12 + for i, n := range ds { 13 + s += n * int64(len(ds) + 1 - i) 14 + } 15 + r := 11 - (s % 11) 16 + if r == 10 { 17 + return 0 18 + } 19 + return r 20 + } 21 + 10 22 type Cpf string 11 23 12 24 func (c Cpf) String() string { ··· 14 26 } 15 27 16 28 func (c Cpf) Validate() bool { 17 - 18 - toInt := func(chars []string) []int { 19 - digits := make([]int, len(chars)) 20 - for index, value := range chars { 21 - converted, _ := strconv.ParseInt(value, 10, 32) 22 - digits[index] = int(converted) 23 - } 24 - return digits 29 + u := c.Unmask() 30 + if len(u) != 11 { 31 + return false 25 32 } 26 33 27 - repeatedNumbers := func(digits []int) bool { 28 - hashTable := map[int]bool{} 29 - for _, digit := range digits { 30 - hashTable[digit] = true 31 - } 32 - return len(hashTable) == 1 33 - 34 - } 35 - 36 - check := func(digits []int, expected int) bool { 37 - sum := 0 38 - for index, number := range digits { 39 - weight := (len(digits) + 1) - index 40 - sum += number * weight 41 - } 42 - result := 11 - (sum % 11) 43 - if result == 10 { 44 - return 0 == expected 34 + var ( 35 + ds = make([]int64, 11) 36 + m = map[int64]bool{} 37 + ) 38 + for i, v := range strings.Split(u, "") { 39 + c, err := strconv.ParseInt(v, 10, 32) 40 + if err != nil { 41 + return false 45 42 } 46 - return result == expected 47 - } 48 - 49 - unmasked := c.Unmask() 50 - if len(unmasked) != 11 { 51 - return false 43 + ds[i] = c 44 + m[c] = true 52 45 } 53 - 54 - digits := toInt(strings.Split(unmasked, "")) 55 - if repeatedNumbers(digits) { 46 + if len(m) == 1 { 56 47 return false 57 48 } 58 49 59 - check1 := check(digits[:9], digits[9]) 60 - check2 := check(digits[:10], digits[10]) 61 - return check1 && check2 62 - 50 + return checksum(ds[:9]) == ds[9] && checksum(ds[:10]) == ds[10] 63 51 } 64 52 65 53 func (c Cpf) Mask() string { 66 - unmasked := c.Unmask() 67 - if len(unmasked) < 11 { 54 + u := c.Unmask() 55 + if len(u) < 11 { 68 56 return string(c) 69 57 } 70 - return fmt.Sprintf("%s.%s.%s-%s", unmasked[:3], unmasked[3:6], unmasked[6:9], unmasked[9:]) 58 + return fmt.Sprintf("%s.%s.%s-%s", u[:3], u[3:6], u[6:9], u[9:]) 71 59 } 72 60 73 61 func (c Cpf) Unmask() string { 74 - pattern := regexp.MustCompile(`\D`) 75 - unmasked := pattern.ReplaceAllString(c.String(), "") 76 - return unmasked 62 + return regexp.MustCompile(`\D`).ReplaceAllString(string(c), "") 77 63 }
+10 -27
cpf_test.go
··· 3 3 import "testing" 4 4 5 5 func TestMask(t *testing.T) { 6 - cpf := Cpf("11111111111") 7 - expect := "111.111.111-11" 8 - got := cpf.Mask() 9 - 10 - if expect != got { 11 - t.Errorf("Expected %s to be %s but got %s", cpf, expect, got) 6 + if got := Cpf("11111111111").Mask(); "111.111.111-11" != got { 7 + t.Errorf("Cpf(\"11111111111\").Mask() = %v; want 111.111.111-11", got) 12 8 } 13 9 } 14 10 15 11 func TestUnmask(t *testing.T) { 16 - cpf := Cpf("111.111.111-11") 17 - expect := "11111111111" 18 - got := cpf.Unmask() 19 - 20 - if expect != got { 21 - t.Errorf("Expected %s to be %s but got %s", cpf, expect, got) 12 + if got := Cpf("111.111.111-11").Unmask(); "11111111111" != got { 13 + t.Errorf("Cpf(\"111.111.111-11\").Unmask() = %v; want 11111111111", got) 22 14 } 23 15 24 16 } 25 17 26 18 func TestValidate(t *testing.T) { 27 - 28 - testTable := []struct { 19 + for _, tc := range []struct { 29 20 cpf Cpf 30 21 expected bool 31 22 }{ ··· 34 25 {Cpf("123"), false}, 35 26 {Cpf("111.111.111-11"), false}, 36 27 {Cpf("123.456.769/01"), false}, 37 - } 38 - 39 - for _, testCase := range testTable { 40 - assertValidate(t, testCase.cpf, testCase.expected) 28 + {Cpf("ABC.DEF.GHI-JK"), false}, 29 + } { 30 + if got := tc.cpf.Validate(); tc.expected != got { 31 + t.Errorf("Cpf(%v).Validate() = %v; want %v", tc.cpf, got, tc.expected) 32 + } 41 33 } 42 34 43 35 } 44 - 45 - func assertValidate(t *testing.T, cpf Cpf, expected bool) { 46 - t.Helper() 47 - got := cpf.Validate() 48 - 49 - if got != expected { 50 - t.Errorf("expected %q to be %t but got %t", cpf, expected, got) 51 - } 52 - }