You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
133 lines
3.3 KiB
Go
133 lines
3.3 KiB
Go
package gma
|
|
|
|
import (
|
|
"bufio"
|
|
"crypto/sha256"
|
|
"encoding/binary"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
)
|
|
|
|
type GMAWriter struct {
|
|
FileHandle *os.File
|
|
gmaStreamWriter *bufio.Writer
|
|
}
|
|
|
|
func NewWriter(fileName string) (_ GMAWriter, err error) {
|
|
return GMAWriter{}.NewWriter(fileName)
|
|
}
|
|
func (w GMAWriter) NewWriter(fileName string) (_ GMAWriter, err error) {
|
|
w.FileHandle, err = os.Create(fileName)
|
|
if err != nil {
|
|
return w, err
|
|
}
|
|
w.gmaStreamWriter = bufio.NewWriter(w.FileHandle)
|
|
return w, nil
|
|
}
|
|
func (w *GMAWriter) WriteHeader(header GMAHeader) (err error) {
|
|
w.gmaStreamWriter.WriteByte('G')
|
|
w.gmaStreamWriter.WriteByte('M')
|
|
w.gmaStreamWriter.WriteByte('A')
|
|
w.gmaStreamWriter.WriteByte('D')
|
|
|
|
w.gmaStreamWriter.WriteByte(header.FormatVersion)
|
|
|
|
steamIDBytes := make([]byte, 8)
|
|
binary.LittleEndian.PutUint64(steamIDBytes, header.SteamID)
|
|
w.gmaStreamWriter.Write(steamIDBytes)
|
|
|
|
timestampBytes := make([]byte, 8)
|
|
binary.LittleEndian.PutUint64(timestampBytes, header.Timestamp)
|
|
w.gmaStreamWriter.Write(timestampBytes)
|
|
|
|
if header.FormatVersion > 1 {
|
|
w.gmaStreamWriter.WriteByte(header.FormatVersionDiscardByte)
|
|
}
|
|
|
|
w.gmaStreamWriter.WriteString(header.Title)
|
|
w.gmaStreamWriter.WriteByte(0)
|
|
w.gmaStreamWriter.WriteString(header.Description)
|
|
w.gmaStreamWriter.WriteByte(0)
|
|
w.gmaStreamWriter.WriteString(header.Author)
|
|
w.gmaStreamWriter.WriteByte(0)
|
|
|
|
addonVersionBytes := make([]byte, 4)
|
|
binary.LittleEndian.PutUint32(addonVersionBytes, uint32(header.AddonVersion))
|
|
w.gmaStreamWriter.Write(addonVersionBytes)
|
|
|
|
w.gmaStreamWriter.Flush()
|
|
|
|
return nil
|
|
}
|
|
func (w *GMAWriter) Close() (err error) {
|
|
return w.FileHandle.Close()
|
|
}
|
|
func (w *GMAWriter) WriteFooterCRC(footerCRC uint32) (err error) {
|
|
crcBytes := make([]byte, 4)
|
|
binary.LittleEndian.PutUint32(crcBytes, footerCRC)
|
|
w.gmaStreamWriter.Write(crcBytes)
|
|
w.gmaStreamWriter.Flush()
|
|
|
|
return nil
|
|
}
|
|
func (w *GMAWriter) WriteFirstType(firstType int32) (err error) {
|
|
firstTypeBytes := make([]byte, 4)
|
|
binary.LittleEndian.PutUint32(firstTypeBytes, uint32(firstType))
|
|
w.gmaStreamWriter.Write(firstTypeBytes)
|
|
w.gmaStreamWriter.Flush()
|
|
|
|
return nil
|
|
}
|
|
func (w *GMAWriter) WriteFileIndex(fileName string, fileSize int64, fileCRC uint32, nextType int32) (err error) {
|
|
w.gmaStreamWriter.WriteString(fileName)
|
|
w.gmaStreamWriter.WriteByte(0)
|
|
|
|
fileSizeBytes := make([]byte, 8)
|
|
binary.LittleEndian.PutUint64(fileSizeBytes, uint64(fileSize))
|
|
w.gmaStreamWriter.Write(fileSizeBytes)
|
|
|
|
crcBytes := make([]byte, 4)
|
|
binary.LittleEndian.PutUint32(crcBytes, fileCRC)
|
|
w.gmaStreamWriter.Write(crcBytes)
|
|
|
|
nextTypeBytes := make([]byte, 4)
|
|
binary.LittleEndian.PutUint32(nextTypeBytes, uint32(nextType))
|
|
w.gmaStreamWriter.Write(nextTypeBytes)
|
|
|
|
w.gmaStreamWriter.Flush()
|
|
|
|
return nil
|
|
}
|
|
|
|
func (w *GMAWriter) WriteFile(reader io.ReadCloser) (err error) {
|
|
//body := new(bytes.Buffer)
|
|
|
|
if _, err = io.Copy(w.gmaStreamWriter, reader); err != nil {
|
|
return err
|
|
}
|
|
/*
|
|
byteCount, err := w.gmaStreamWriter.Write(body.Bytes())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if byteCount != body.Len() {
|
|
return fmt.Errorf("Only wrote %d bytes from %d", byteCount, body.Len())
|
|
}
|
|
*/
|
|
err = w.gmaStreamWriter.Flush()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (w GMAWriter) GetSHA256() (hash string, err error) {
|
|
shaHasher := sha256.New()
|
|
if _, err := io.Copy(shaHasher, w.FileHandle); err != nil {
|
|
return "", err
|
|
}
|
|
return fmt.Sprintf("%x", shaHasher.Sum(nil)), nil
|
|
}
|