package main import ( "errors" "fmt" "os" "strings" "github.com/pektezol/bitreader" "github.com/pektezol/sdp.go/pkg/packets" "github.com/pektezol/sdp.go/pkg/writer" ) type Demo struct { Headers packets.Headers `json:"headers"` Messages []packets.Message `json:"messages"` } type Parser struct { DemoPath string writer strings.Builder } func NewParser(demoPath string) *Parser { return &Parser{ DemoPath: demoPath, } } const littleEndian bool = true func main() { if len(os.Args) != 2 { fmt.Println("specify file in command line arguments") os.Exit(1) } parser := NewParser(os.Args[1]) _, err := parser.ParseDemos() if err != nil { fmt.Println(err.Error()) os.Exit(1) } fmt.Println(parser.GetOutput()) } func (p *Parser) GetOutput() string { return p.writer.String() } func (p *Parser) ParseDemos() ([]Demo, error) { writer.AppendLine("Generated By: github.com/pektezol/sdp.go") files, err := os.ReadDir(p.DemoPath) if err != nil { // not a directory file, err := os.Open(p.DemoPath) if err != nil { return []Demo{}, err } defer file.Close() reader := bitreader.NewReader(file, littleEndian) demo := demoParserHandler(reader, file.Name()) p.writer = writer.GetWriter() return []Demo{demo}, nil } else { demos := []Demo{} // directory for _, fileinfo := range files { if len(fileinfo.Name()) > 4 && fileinfo.Name()[len(fileinfo.Name())-4:] == ".dem" { file, err := os.Open(p.DemoPath + fileinfo.Name()) if err != nil { return []Demo{}, err } defer file.Close() reader := bitreader.NewReader(file, littleEndian) demo := demoParserHandler(reader, file.Name()) demos = append(demos, demo) } } p.writer = writer.GetWriter() if len(demos) == 0 { return demos, errors.New("no demo found in given directory") } return demos, nil } } func demoParserHandler(reader *bitreader.Reader, filename string) Demo { demo := Demo{} writer.AppendLine("\nFile Name: %s", filename) // this is for recovering after a panic inside parse headers and packet. // this approach was taken since error handling bitreader functions would take a long time. defer func() { if err := recover(); err != nil { writer.AppendLine("failed to parse demo: %v", err) } }() demo.Headers = packets.ParseHeaders(reader) for { message := packets.ParseMessage(reader) demo.Messages = append(demo.Messages, message) if message.PacketType == 7 { break } } return demo }