-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathreader.go
85 lines (67 loc) · 1.65 KB
/
reader.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
package unneko
import (
"errors"
"fmt"
"os"
"strings"
)
type ExtractedFile struct {
fileData []byte
filePath string
}
func (f *ExtractedFile) Data() []byte {
return f.fileData
}
func (f *ExtractedFile) Path() string {
return f.filePath
}
type Reader struct {
neko *nekoData
cCond *checksumCompleteCond
namer *fileNamer
}
func NewReaderFromFile(file string) (*Reader, error) {
inputFile, err := os.ReadFile(file)
if err != nil {
return nil, fmt.Errorf("unable to read input file: %v", err)
}
isPatch := strings.HasSuffix(strings.ToLower(file), ".patch.nekodata")
return NewReader(inputFile, isPatch)
}
func NewReader(data []byte, isPatchFile bool) (*Reader, error) {
neko, err := newNekoData(data, isPatchFile)
if err != nil {
return nil, err
}
checksumFiles := findChecksumFiles(neko)
if len(checksumFiles) == 0 {
return nil, fmt.Errorf("unable to find checksum file")
}
return &Reader{
neko: neko,
cCond: newChecksumCompleteCond(checksumFiles),
namer: newFileNamer(checksumFiles),
}, nil
}
func (r *Reader) HasNext() bool {
return !r.cCond.FoundAll() && !r.neko.fullyRead()
}
func (r *Reader) Next() (*ExtractedFile, error) {
if isUncompressedFile(r.neko) {
data := extractUncompressed(r.neko, r.cCond)
return r.newExtractedFile(data), nil
}
headerBytes := tryUncompressHeader(r.neko, 1)
if len(headerBytes) == 0 {
return nil, errors.New("file not extractable")
}
data := uncompressNeko(r.neko, r.cCond)
return r.newExtractedFile(data), nil
}
func (r *Reader) newExtractedFile(data []byte) *ExtractedFile {
r.cCond.MarkAsFound(data)
return &ExtractedFile{
fileData: data,
filePath: r.namer.GetName(data),
}
}