123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- package inns
- // The package implements the basic
- // Russian Federation INN format
- // storing it in int64 to keep
- // searching and storing as
- // quick as possible.
- import (
- "strings"
- "unicode"
- "strconv"
- "fmt"
- "slices"
- )
- type Type uint8
- const (
- TypeIncorrect Type = iota
- TypeLegal
- TypeIndividual
- )
- func removeSpaces(s string) string {
- return strings.Map(func(r rune) rune{
- if unicode.IsSpace(r) {
- return -1
- }
- return r
- }, s)
- }
- type INN int64
- func NewFromInt64(innRaw int64) (INN, error) {
- inn := INN(innRaw)
- if !inn.isCorrectLen() {
- return -1, ErrIncorrectLen
- }
- if !inn.isSumCorrect() {
- return -1, ErrSumsNotMatch
- }
- return inn, nil
- }
- func (inn INN) IsCorrect() bool {
- _, err := NewFromInt64(int64(inn))
- return err == nil
- }
- // Convert string with spaces into the INN
- // and return error if anything is wrong with it.
- func NewFromStr(str string) (INN, error) {
- str = removeSpaces(str)
- innRaw, err := strconv.ParseInt(str, 10, 64)
- if err != nil {
- return -1, ErrIncorrectFormat
- }
- return NewFromInt64(innRaw)
- }
- func (inn INN) Type() Type {
- ln := inn.length()
- switch ln {
- case 9, 10:
- return TypeLegal
- case 11, 12:
- return TypeIndividual
- }
- return TypeIncorrect
- }
- func (inn INN) length() int {
- ln := 0
- for {
- if inn == 0 {
- break
- }
- inn /= 10
- ln++
- }
- if ln == 9 || ln == 11 {
- ln++
- }
- return ln
- }
- func (inn INN) isCorrectLen() bool {
- ln := inn.length()
- if ln == 9 || ln == 11 {
- ln++
- }
- return ln == 10 || ln == 12
- }
- var (
- // Koefs for the control sum.
- innSum10 = [9]int64{
- 2, 4, 10, 3, 5, 9, 4, 6, 8,
- }
- innSum11 = [10]int64{
- 7, 2, 4, 10, 3, 5, 9, 4, 6, 8,
- }
- innSum12 = [11]int64{
- 3, 7, 2, 4, 10, 3, 5, 9, 4, 6, 8,
- }
- )
- // Get the integer representation of digits in string INN.
- func (inn INN) digits() []int64 {
- ln := inn.length()
- v := int64(inn)
- ret := make([]int64, ln)
- for i := 0 ; i<ln ; i++{
- ret[i] = v % 10
- v /= 10
- }
- slices.Reverse(ret)
- return ret
- }
- //
- func (inn INN) specifiedSum() int64 {
- ln := inn.length()
- v := int64(inn)
- switch ln {
- case 10:
- return v%10
- case 12:
- return v%100
- default:
- return -1
- }
- }
- // Returns the supposed control sum rune. (the last number)
- func (inn INN) sum() int64 {
- d := inn.digits()
- ln := inn.length()
- switch ln {
- case 10 :
- var n10 int64
- for i, ni := range d[:9] {
- n10 += innSum10[i] * ni
- }
- n10 = (n10 % 11) % 10
- return n10
- case 12 :
- var n11 int64
- for i, ni := range d[:10] {
- n11 += innSum11[i] * ni
- }
- n11 = (n11 % 11) % 10
- var n12 int64
- for i, ni := range d[:10] {
- n12 += innSum12[i] * ni
- }
- n12 += innSum12[10] * n11
- n12 = (n12 % 11) % 10
- return n11*10 + n12
- }
- return -1
- }
- func (inn INN) isSumCorrect() bool {
- return inn.specifiedSum() == inn.sum()
- }
- func (inn INN) String() string {
- return fmt.Sprintf("%d", inn)
- }
- // Fancy way to print INN with space delimiters.
- func (inn INN) Fancy() string {
- ln := inn.length()
- str := fmt.Sprintf("%d", inn)
- // Adding zero depending on length.
- if len(str) == 9 || len(str) == 11 {
- str = "0"+str
- }
- switch ln {
- case 10 :
- return fmt.Sprintf("%s %s %s", str[:4], str[4:9], str[9:])
- case 12 :
- return fmt.Sprintf("%s %s %s", str[:4], str[4:10], str[10:])
- }
- // Reaching the point if the length is incorrect.
- return "<"+ErrIncorrectLen.Error()+">"
- }
|