JOJ3/internal/executors/sandbox/convert.go
张泊明518370910136 b40072a485
All checks were successful
build-image / create-empty-commit (push) Successful in 5s
checks / build (push) Successful in 1m19s
feat: rename module
2024-09-30 22:04:18 -04:00

178 lines
4.6 KiB
Go

package sandbox
import (
"log/slog"
"os"
"path/filepath"
"strings"
"github.com/criyle/go-judge/pb"
"github.com/joint-online-judge/JOJ3/internal/stage"
)
// copied from https://github.com/criyle/go-judge/blob/master/cmd/go-judge-shell/grpc.go
func convertPBCmd(cmd []stage.Cmd) []*pb.Request_CmdType {
var ret []*pb.Request_CmdType
for _, c := range cmd {
ret = append(ret, &pb.Request_CmdType{
Args: c.Args,
Env: c.Env,
Tty: c.TTY,
Files: convertPBFiles([]*stage.CmdFile{c.Stdin, c.Stdout, c.Stderr}),
CpuTimeLimit: c.CPULimit,
ClockTimeLimit: c.ClockLimit,
MemoryLimit: c.MemoryLimit,
StackLimit: c.StackLimit,
ProcLimit: c.ProcLimit,
CpuRateLimit: c.CPURateLimit,
CpuSetLimit: c.CPUSetLimit,
DataSegmentLimit: c.DataSegmentLimit,
AddressSpaceLimit: c.AddressSpaceLimit,
CopyIn: convertPBCopyIn(c.CopyIn, c.CopyInDir),
CopyOut: convertPBCopyOut(c.CopyOut),
CopyOutCached: convertPBCopyOut(c.CopyOutCached),
CopyOutMax: c.CopyOutMax,
CopyOutDir: c.CopyOutDir,
Symlinks: convertSymlink(c.CopyIn),
})
}
return ret
}
func convertPBCopyIn(
copyIn map[string]stage.CmdFile, copyInDir string,
) map[string]*pb.Request_File {
if copyInDir != "" {
_ = filepath.Walk(copyInDir,
func(path string, info os.FileInfo, err error) error {
if err != nil {
return nil
}
absPath, err := filepath.Abs(path)
if err != nil {
return nil
}
if !info.IsDir() {
copyIn[path] = stage.CmdFile{Src: &absPath}
}
return nil
})
}
rt := make(map[string]*pb.Request_File, len(copyIn))
for k, i := range copyIn {
if i.Symlink != nil {
continue
}
rt[k] = convertPBFile(i)
}
return rt
}
func convertPBCopyOut(copyOut []string) []*pb.Request_CmdCopyOutFile {
rt := make([]*pb.Request_CmdCopyOutFile, 0, len(copyOut))
for _, n := range copyOut {
optional := false
if strings.HasSuffix(n, "?") {
optional = true
n = strings.TrimSuffix(n, "?")
}
rt = append(rt, &pb.Request_CmdCopyOutFile{
Name: n,
Optional: optional,
})
}
return rt
}
func convertSymlink(copyIn map[string]stage.CmdFile) map[string]string {
ret := make(map[string]string)
for k, v := range copyIn {
if v.Symlink == nil {
continue
}
ret[k] = *v.Symlink
}
return ret
}
func convertPBFiles(files []*stage.CmdFile) []*pb.Request_File {
var ret []*pb.Request_File
for _, f := range files {
if f == nil {
ret = append(ret, nil)
} else {
ret = append(ret, convertPBFile(*f))
}
}
return ret
}
func convertPBFile(i stage.CmdFile) *pb.Request_File {
switch {
case i.Src != nil:
if !filepath.IsAbs(*i.Src) {
absPath, err := filepath.Abs(*i.Src)
if err == nil {
i.Src = &absPath
}
}
s, err := os.ReadFile(*i.Src)
if err != nil {
s = []byte{}
slog.Error("read file error", "path", *i.Src, "error", err)
}
return &pb.Request_File{File: &pb.Request_File_Memory{Memory: &pb.Request_MemoryFile{Content: s}}}
case i.Content != nil:
s := strToBytes(*i.Content)
return &pb.Request_File{File: &pb.Request_File_Memory{Memory: &pb.Request_MemoryFile{Content: s}}}
case i.FileID != nil:
return &pb.Request_File{File: &pb.Request_File_Cached{Cached: &pb.Request_CachedFile{FileID: *i.FileID}}}
case i.Name != nil && i.Max != nil:
return &pb.Request_File{File: &pb.Request_File_Pipe{Pipe: &pb.Request_PipeCollector{Name: *i.Name, Max: *i.Max, Pipe: i.Pipe}}}
case i.StreamIn:
return &pb.Request_File{File: &pb.Request_File_StreamIn{}}
case i.StreamOut:
return &pb.Request_File{File: &pb.Request_File_StreamOut{}}
}
return nil
}
func convertPBResult(res []*pb.Response_Result) []stage.ExecutorResult {
var ret []stage.ExecutorResult
for _, r := range res {
ret = append(ret, stage.ExecutorResult{
Status: stage.Status(r.Status),
ExitStatus: int(r.ExitStatus),
Error: r.Error,
Time: r.Time,
RunTime: r.RunTime,
Memory: r.Memory,
Files: convertFiles(r.Files),
Buffs: r.Files,
FileIDs: r.FileIDs,
FileError: convertPBFileError(r.FileError),
})
}
return ret
}
func convertFiles(buf map[string][]byte) map[string]string {
ret := make(map[string]string, len(buf))
for k, v := range buf {
ret[k] = byteArrayToString(v)
}
return ret
}
func convertPBFileError(fe []*pb.Response_FileError) []stage.FileError {
var ret []stage.FileError
for _, v := range fe {
ret = append(ret, stage.FileError{
Name: v.Name,
Type: stage.FileErrorType(v.Type),
Message: v.Message,
})
}
return ret
}