Files
cloudpods/pkg/webconsole/guac/instruction.go
2023-11-28 10:47:04 +08:00

85 lines
1.9 KiB
Go

// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package guac
import (
"fmt"
"strconv"
"yunion.io/x/pkg/errors"
)
type Instruction struct {
Opcode string
Args []string
}
func NewInstruction(op string, args ...string) *Instruction {
return &Instruction{
Opcode: op,
Args: args,
}
}
func (i *Instruction) String() string {
ret := fmt.Sprintf("%d.%s", len(i.Opcode), i.Opcode)
for _, value := range i.Args {
ret += fmt.Sprintf(",%d.%s", len(value), value)
}
ret += ";"
return ret
}
func parse(buf []byte) ([]*Instruction, []byte, error) {
ret := []*Instruction{}
if len(buf) == 0 {
return ret, []byte{}, nil
}
start, opcode, args := 0, "", []string{}
begin := 0
for i := 0; i < len(buf); i++ {
switch buf[i] {
case ',':
start = i + 1
case '.':
length, err := strconv.Atoi(string(buf[start:i]))
if err != nil {
return nil, []byte{}, errors.Wrapf(err, "Atoi(%s)", string(buf[start:i]))
}
if i+length+1 > len(buf) {
return ret, buf[begin:], nil
}
str := string(buf[i+1 : i+length+1])
if len(opcode) == 0 {
opcode = str
} else {
args = append(args, str)
}
i += length
case ';':
start = i + 1
begin = i + 1
instruction := NewInstruction(opcode, args...)
ret = append(ret, instruction)
opcode = ""
args = []string{}
}
}
if buf[len(buf)-1] != ';' {
return ret, buf[begin:], nil
}
return ret, []byte{}, nil
}