forked from mitch000001/go-hbci
/
segment_extractor.go
77 lines (69 loc) · 2.17 KB
/
segment_extractor.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
package message
import (
"bytes"
"fmt"
"github.com/mitch000001/go-hbci/token"
)
// NewSegmentExtractor returns a new SegmentExtractor which extracts segments
// from messageBytes
func NewSegmentExtractor(messageBytes []byte) *SegmentExtractor {
return &SegmentExtractor{rawMessage: messageBytes}
}
// A SegmentExtractor extracts segments from a raw message and caches its
// results
type SegmentExtractor struct {
rawMessage []byte
segments [][]byte
}
// Extract extract segment byte slices from the message. It will return a copy
// of the result so it is safe to manipulate it
func (s *SegmentExtractor) Extract() ([][]byte, error) {
var current []byte
lexer := token.NewLexer("SegmentExtractor", s.rawMessage)
for lexer.HasNext() {
t := lexer.Next()
if t.Type() == token.ERROR {
return nil, fmt.Errorf("%T: SyntaxError at position %d: %q\n(%q)", s, t.Pos(), t.Value(), s.rawMessage)
}
current = append(current, t.Value()...)
if t.Type() == token.SEGMENT_END_MARKER {
s.segments = append(s.segments, current)
current = []byte{}
}
}
result := make([][]byte, len(s.segments))
copy(result, s.segments)
return result, nil
}
// FindSegment searches for a given ID and returns the first appearing segment
// bytes if present
func (s *SegmentExtractor) FindSegment(id string) []byte {
byteID := []byte(id)
for _, segment := range s.segments {
if bytes.HasPrefix(segment, byteID) {
return segment
}
}
return nil
}
// FindSegments finds all segments for a given ID and returns them if present
func (s *SegmentExtractor) FindSegments(id string) [][]byte {
segmentMap := make(map[string][][]byte)
for _, segment := range s.segments {
segmentID := bytes.SplitN(segment, []byte(":"), 2)[0]
mappedSegments, ok := segmentMap[string(segmentID)]
if !ok {
mappedSegments = make([][]byte, 0)
}
mappedSegments = append(mappedSegments, segment)
segmentMap[string(segmentID)] = mappedSegments
}
return segmentMap[id]
}
// Segments returns all found segments in order of appearance. It is safe to
// manipulate the result as it is a copy.
func (s *SegmentExtractor) Segments() [][]byte {
result := make([][]byte, len(s.segments))
copy(result, s.segments)
return result
}