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

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 uint32) (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, 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
}