package hotline
import (
+ "bytes"
"encoding/binary"
- "github.com/jhalter/mobius/concat"
+ "io"
+ "slices"
)
-// FileNameWithInfo field content is presented in this structure:
-// Type 4 Folder (‘fldr’) or other
-// Creator 4
-// File size 4
-// 4 Reserved?
-// Name script 2
-// Name size 2
-// Name data size
type FileNameWithInfo struct {
- Type []byte // file type code
- Creator []byte // File creator code
- FileSize []byte // File Size in bytes
- RSVD []byte
- NameScript []byte // TODO: What is this?
- NameSize []byte // Length of name field
- Name []byte // File name
+ 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[:]))
}
-func (f FileNameWithInfo) Payload() []byte {
- name := f.Name
- nameSize := make([]byte, 2)
- binary.BigEndian.PutUint16(nameSize, uint16(len(name)))
-
- return concat.Slices(
- f.Type,
- f.Creator,
- f.FileSize,
- []byte{0, 0, 0, 0},
- f.NameScript,
- 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) Read(p []byte) (n int, err error) {
- // TODO: check p for expected len
- f.Type = p[0:4]
- f.Creator = p[4:8]
- f.FileSize = p[8:12]
- f.RSVD = p[12:16]
- f.NameScript = p[16:18]
- f.NameSize = p[18:20]
- f.Name = p[20:]
-
- return len(p), err
+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
}