// Copyright 2025, Command Line Inc. // SPDX-License-Identifier: Apache-2.0 package packetparser import ( "bufio" "bytes" "fmt" "io" "log" "github.com/wavetermdev/waveterm/pkg/util/utilfn" ) type PacketParser struct { Reader io.Reader Ch chan []byte } func ParseWithLinesChan(input chan utilfn.LineOutput, packetCh chan []byte, rawCh chan []byte) { defer close(packetCh) defer close(rawCh) for { // note this line doesn't have a trailing newline line, ok := <-input if !ok { return } if line.Error != nil { log.Printf("ParseWithLinesChan: error reading line: %v", line.Error) return } if len(line.Line) <= 1 { // just a blank line continue } if bytes.HasPrefix([]byte(line.Line), []byte{'#', '#', 'N', '{'}) && bytes.HasSuffix([]byte(line.Line), []byte{'}'}) { // strip off the leading "##" packetCh <- []byte(line.Line[3:len(line.Line)]) } else { rawCh <- []byte(line.Line) } } } func Parse(input io.Reader, packetCh chan []byte, rawCh chan []byte) error { bufReader := bufio.NewReader(input) defer close(packetCh) defer close(rawCh) for { // note this line does have a trailing newline line, err := bufReader.ReadBytes('\n') if err == io.EOF { return nil } if err != nil { return err } if len(line) <= 1 { // just a blank line continue } if bytes.HasPrefix(line, []byte{'#', '#', 'N', '{'}) && bytes.HasSuffix(line, []byte{'}', '\n'}) { // strip off the leading "##" and trailing "\n" (single byte) packetCh <- line[3 : len(line)-1] } else { rawCh <- line } } } func WritePacket(output io.Writer, packet []byte) error { if len(packet) < 2 { return nil } if packet[0] != '{' || packet[len(packet)-1] != '}' { return fmt.Errorf("invalid packet, must start with '{' and end with '}'") } fullPacket := make([]byte, 0, len(packet)+5) // we add the extra newline to make sure the ## appears at the beginning of the line // since writer isn't buffered, we want to send this all at once fullPacket = append(fullPacket, '\n', '#', '#', 'N') fullPacket = append(fullPacket, packet...) fullPacket = append(fullPacket, '\n') _, err := output.Write(fullPacket) return err }