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" }