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.
ntool-biz/ngochess/gtp/serializer_gtp.go

115 lines
2.3 KiB
Go

package gtp
import (
"errors"
"fmt"
"git.noahlan.cn/noahlan/ntool/nbyte"
"git.noahlan.cn/noahlan/ntool/nstr"
"regexp"
"strings"
)
var (
TabRegex = regexp.MustCompile(`\t`)
IdRegex = regexp.MustCompile(`\s`)
)
type GTPSerializer struct {
contentBuf strings.Builder
firstLine bool
//
lastResp *GTPResponse
}
func NewGTPSerializer() *GTPSerializer {
ret := &GTPSerializer{
contentBuf: strings.Builder{},
}
ret.reset()
return ret
}
func (s *GTPSerializer) Marshal(v any) ([]byte, error) {
ret, ok := v.(*GTPCommand)
if !ok {
return nil, errors.New(fmt.Sprintf("参数类型必须为 %T", GTPCommand{}))
}
// ret arg0 arg1 arg2 ...
// Cmd arg0 arg1 arg2 ...
sb := strings.Builder{}
if ret.ID != "" {
sb.WriteString(ret.ID)
sb.WriteString(" ")
}
sb.WriteString(ret.Cmd)
sb.WriteString(" ")
sb.WriteString(strings.Join(ret.Args, " "))
return []byte(sb.String()), nil
}
func (s *GTPSerializer) reset() {
s.contentBuf.Reset()
s.firstLine = true
s.lastResp = nil
}
func (s *GTPSerializer) Unmarshal(line string) (*GTPResponse, bool) {
// replace \t and trimSpace
line = strings.TrimSpace(TabRegex.ReplaceAllString(line, " "))
// 是否第一行
s.firstLine = nstr.ContainsOne(line, []string{"=", "?"})
if len(line) == 0 {
defer s.reset()
if s.firstLine {
s.lastResp = &GTPResponse{
ID: "",
Content: s.contentBuf.String(),
Err: errors.New("unknown"),
}
return s.lastResp, true
} else {
// end line
content := s.contentBuf.String()
// remove last '\n'
cLen := len(content)
if cLen > 0 && content[cLen-1] == '\n' {
content = content[:cLen-1]
}
if s.lastResp.Err == nil {
s.lastResp.Content = content
} else {
s.lastResp.Err = errors.New(content)
}
return s.lastResp, true
}
}
if s.firstLine {
s.lastResp = &GTPResponse{}
// 第一行,处理 err, id 等内容
hasErr := line[0] == '?'
hasId := len(line) >= 2 && nbyte.IsDigit(line[1])
line = line[1:]
if hasId {
s.lastResp.ID = IdRegex.Split(line, -1)[0]
line = line[len(s.lastResp.ID):]
}
if hasErr {
s.lastResp.Err = errors.New("接收GTP错误消息")
}
}
// 填充内容直至末尾行
s.contentBuf.WriteString(strings.TrimSpace(line))
s.contentBuf.WriteByte('\n')
return nil, false
}