-
Notifications
You must be signed in to change notification settings - Fork 0
/
parser.go
115 lines (103 loc) · 3.15 KB
/
parser.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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package go_mrz_parser
import (
"github.com/okieraised/go-mrz-scanner/constants"
"github.com/okieraised/go-mrz-scanner/internal/parser"
"github.com/okieraised/go-mrz-scanner/mrz_errors"
"github.com/okieraised/go-mrz-scanner/utils"
"strings"
)
// MRZParser defines the structure of the parser.
// - mrzType: type of the MRZ string
// - components: parts of the MRZ string
type MRZParser struct {
mrzType int
components []string
}
// NewMRZStringParser receives a single mrz string with each line separated by newline character.
func NewMRZStringParser(mrzStr string) *MRZParser {
components := make([]string, 0)
if strings.Contains(mrzStr, "\n") {
components = strings.Split(mrzStr, "\n")
} else {
if len(mrzStr) == constants.Type1TotalNumberOfCharacters {
components = []string{
mrzStr[:constants.Type1NumberOfCharactersPerLine],
mrzStr[constants.Type1NumberOfCharactersPerLine : 2*constants.Type1NumberOfCharactersPerLine],
mrzStr[2*constants.Type1NumberOfCharactersPerLine:],
}
} else if len(mrzStr) == constants.Type2TotalNumberOfCharacters {
components = []string{
mrzStr[:constants.Type2NumberOfCharactersPerLine],
mrzStr[constants.Type2NumberOfCharactersPerLine:],
}
} else {
components = []string{
mrzStr[:constants.Type3NumberOfCharactersPerLine],
mrzStr[constants.Type3NumberOfCharactersPerLine:],
}
}
}
return &MRZParser{
components: components,
}
}
// NewMRZLineParser receives the mrz string slices.
func NewMRZLineParser(mrzLines []string) *MRZParser {
return &MRZParser{
components: mrzLines,
}
}
// Parse validates and parses the MRZ information
func (p *MRZParser) Parse() (*parser.MRZResult, error) {
err := p.validate()
if err != nil {
return &parser.MRZResult{}, err
}
var mrzParser parser.IMRZParser
switch p.mrzType {
case constants.MRZType1:
mrzParser = parser.NewTD1()
case constants.MRZType2:
mrzParser = parser.NewTD2()
case constants.MRZType3:
mrzParser = parser.NewTD3()
default:
return &parser.MRZResult{}, mrz_errors.ErrInvalidMRZType
}
parse, err := mrzParser.Parse(p.components)
if err != nil {
return &parser.MRZResult{}, err
}
return parse, nil
}
// validate checks the input MRZ for formatting errors
func (p *MRZParser) validate() error {
mrzType := 0
switch len(p.components) {
case 3:
for _, line := range p.components {
if len(line) != constants.Type1NumberOfCharactersPerLine {
return mrz_errors.ErrTD1InvalidLineLength
}
}
mrzType = constants.MRZType1
case 2:
characterCount := make([]int, 0)
for _, line := range p.components {
if len(line) != constants.Type2NumberOfCharactersPerLine && len(line) != constants.Type3NumberOfCharactersPerLine {
return mrz_errors.ErrGenericInvalidMRZLinesLength
}
characterCount = append(characterCount, len(line))
}
if utils.CheckSame(characterCount) && characterCount[0] == constants.Type2NumberOfCharactersPerLine {
mrzType = constants.MRZType2
}
if utils.CheckSame(characterCount) && characterCount[0] == constants.Type3NumberOfCharactersPerLine {
mrzType = constants.MRZType3
}
default:
return mrz_errors.ErrGenericInvalidMRZLines
}
p.mrzType = mrzType
return nil
}