aboutsummaryrefslogtreecommitdiff
path: root/hotline/file_name_with_info.go
blob: 3a4a79563bdbde613e399173b3cec4edc6cfba82 (plain)
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
package hotline

import (
	"bytes"
	"encoding/binary"
	"io"
	"slices"
)

type FileNameWithInfo struct {
	FileNameWithInfoHeader
	Name []byte // File Name

	readOffset int // Internal offset to track read progress
}

// FileNameWithInfoHeader contains the fixed length fields of FileNameWithInfo
type FileNameWithInfoHeader struct {
	Type       [4]byte // File type code
	Creator    [4]byte // File creator code
	FileSize   [4]byte // File Size in bytes
	RSVD       [4]byte
	NameScript [2]byte // ??
	NameSize   [2]byte // Length of Name field
}

func (f *FileNameWithInfoHeader) nameLen() int {
	return int(binary.BigEndian.Uint16(f.NameSize[:]))
}

// Read implements io.Reader for FileNameWithInfo
func (f *FileNameWithInfo) Read(p []byte) (int, error) {
	buf := slices.Concat(
		f.Type[:],
		f.Creator[:],
		f.FileSize[:],
		f.RSVD[:],
		f.NameScript[:],
		f.NameSize[:],
		f.Name,
	)

	if f.readOffset >= len(buf) {
		return 0, io.EOF // All bytes have been read
	}

	n := copy(p, buf[f.readOffset:])
	f.readOffset += n

	return n, nil
}

func (f *FileNameWithInfo) Write(p []byte) (int, error) {
	err := binary.Read(bytes.NewReader(p), binary.BigEndian, &f.FileNameWithInfoHeader)
	if err != nil {
		return 0, err
	}
	headerLen := binary.Size(f.FileNameWithInfoHeader)
	f.Name = p[headerLen : headerLen+f.nameLen()]

	return len(p), nil
}