Skip to content

Commit 74b5b13

Browse files
committed
refactor: proto
1 parent 5d74bb2 commit 74b5b13

File tree

6 files changed

+463
-305
lines changed

6 files changed

+463
-305
lines changed

core/internal/api/parse.go

Lines changed: 35 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -6,141 +6,70 @@ package api
66

77
import (
88
"errors"
9-
"strconv"
9+
"strings"
1010

11-
"github.com/SwanHubX/SwanLab/core/pkg/pb"
12-
)
11+
"google.golang.org/protobuf/types/known/structpb"
1312

14-
// Some constants for the parser.
15-
const (
16-
minRangeLen = 2
13+
"github.com/SwanHubX/SwanLab/core/pkg/pb"
1714
)
1815

1916
// Parser provides methods to parse proto messages to JSON sent to the SwanLab Server.
2017
type Parser struct {
2118
}
2219

23-
// convertRange will convert the YRange from a proto message (like ["0", "None"]) to a JSON-compatible format(like [0, null]).
24-
// We expect the input to be a slice of strings with 2 elements, any other length will return an empty slice.
25-
func (p *Parser) convertRange(r []string) []interface{} {
26-
var left, right interface{} = nil, nil
27-
// must be at least 2 elements
28-
if len(r) != minRangeLen {
29-
return []interface{}{}
30-
}
31-
if val, err := strconv.Atoi(r[0]); err == nil {
32-
left = val
33-
}
34-
if val, err := strconv.Atoi(r[1]); err == nil {
35-
right = val
36-
}
37-
return []interface{}{left, right}
38-
}
39-
40-
// validateColumnClass will validate the columnClass.
41-
func (p *Parser) validateColumnClass(record *pb.ColumnRecord) (string, error) {
42-
var class string
43-
switch record.GetColumnClass() {
44-
case pb.ColumnRecord_COL_CUSTOM:
45-
class = "CUSTOM"
46-
case pb.ColumnRecord_COL_SYSTEM:
47-
class = "SYSTEM"
48-
default:
49-
return "", errors.New("invalid column class: " + record.GetColumnClass().String())
50-
}
51-
return class, nil
52-
}
53-
54-
// validateColumnType will validate the columnType.
55-
func (p *Parser) validateColumnType(record *pb.ColumnRecord) (string, error) {
56-
switch record.GetColumnType() {
57-
case pb.ColumnRecord_COL_FLOAT:
58-
return "FLOAT", nil
59-
case pb.ColumnRecord_COL_IMAGE:
60-
return "IMAGE", nil
61-
case pb.ColumnRecord_COL_AUDIO:
62-
return "AUDIO", nil
63-
case pb.ColumnRecord_COL_TEXT:
64-
return "TEXT", nil
65-
case pb.ColumnRecord_COL_OBJECT3D:
66-
return "OBJECT3D", nil
67-
case pb.ColumnRecord_COL_MOLECULE:
68-
return "MOLECULE", nil
69-
case pb.ColumnRecord_COL_ECHARTS:
70-
return "ECHARTS", nil
71-
default:
72-
return "", errors.New("invalid column type: " + record.GetColumnType().String())
73-
}
74-
}
75-
76-
// validateSectionType will validate the sectionType.
77-
func (p *Parser) validateSectionType(record *pb.ColumnRecord) (string, error) {
78-
var sectionType string
79-
switch record.GetSectionType() {
80-
case pb.ColumnRecord_SEC_CUSTOM:
81-
sectionType = "CUSTOM"
82-
case pb.ColumnRecord_SEC_SYSTEM:
83-
sectionType = "SYSTEM"
84-
case pb.ColumnRecord_SEC_PINNED:
85-
sectionType = "PINNED"
86-
case pb.ColumnRecord_SEC_HIDDEN:
87-
sectionType = "HIDDEN"
88-
case pb.ColumnRecord_SEC_PUBLIC:
89-
sectionType = "PUBLIC"
90-
default:
91-
return "", errors.New("invalid section type: " + record.GetSectionType().String())
92-
}
93-
return sectionType, nil
94-
}
95-
20+
// ColumnDTO represents the data transfer object for a column record.
21+
// We use RESTFul naming conventions for the fields.
9622
type ColumnDTO struct {
97-
Class string `json:"class"`
98-
Type string `json:"type"`
99-
Key string `json:"key"`
100-
Name string `json:"name,omitempty"`
101-
Error interface{} `json:"error,omitempty"`
102-
SectionName string `json:"section_name,omitempty"`
103-
SectionType string `json:"section_type,omitempty"`
23+
Class string `json:"class"`
24+
Type string `json:"type"`
25+
Key string `json:"key"`
26+
Name string `json:"name,omitempty"`
27+
// e.g. {data_class: '', excepted: ''}
28+
Error *structpb.Struct `json:"error,omitempty"`
29+
SectionName string `json:"section_name,omitempty"`
30+
SectionType string `json:"section_type,omitempty"`
10431
// allow [0, 100] or [0, null] for y_range
105-
YRange []interface{} `json:"y_range,omitempty"`
106-
ChartIndex string `json:"chart_index,omitempty"`
107-
ChartName string `json:"chart_name,omitempty"`
108-
MetricName string `json:"metric_name,omitempty"`
109-
MetricColor []string `json:"metric_color,omitempty"`
32+
YRange []*int64 `json:"y_range,omitempty"`
33+
ChartIndex string `json:"chart_index,omitempty"`
34+
ChartName string `json:"chart_name,omitempty"`
35+
MetricName string `json:"metric_name,omitempty"`
36+
MetricColor []string `json:"metric_color,omitempty"`
11037
}
11138

112-
// ParseColumnRecord parses a ColumnRecord proto message into a map[string]interface{} for JSON serialization.
39+
// ParseColumnRecord parses a ColumnRecord proto message into ColumnDTO.
11340
// Attention: y_range should be serialized to [0, null] in JSON, not ["0", "None"].
11441
func (p *Parser) ParseColumnRecord(record *pb.ColumnRecord) (ColumnDTO, error) {
11542
// 1. parse the y_range, if error, yRange will be nil
116-
yRange := p.convertRange(record.GetChartYRange())
43+
var yRange []*int64
44+
if record.GetChartYRange() != nil {
45+
yRange = []*int64{
46+
//nolint:protogetter // We need pointers to represent null during JSON serialization.
47+
record.GetChartYRange().Minval,
48+
//nolint:protogetter // We need pointers to represent null during JSON serialization.s
49+
record.GetChartYRange().Maxval,
50+
}
51+
}
11752
// 2. parse the enum type
11853
// 2.1 column class
119-
class, err := p.validateColumnClass(record)
120-
if err != nil {
121-
return ColumnDTO{}, err
122-
}
54+
columnClass := strings.TrimPrefix(record.GetColumnClass().String(), "COL_CLASS_")
12355
// 2.2 column type
124-
columnType, err := p.validateColumnType(record)
125-
if err != nil {
126-
return ColumnDTO{}, err
56+
if record.GetColumnType() == pb.ColumnRecord_COL_UNKNOWN {
57+
return ColumnDTO{}, errors.New("column type is unknown")
12758
}
59+
columnType := strings.TrimPrefix(record.GetColumnType().String(), "COL_")
12860
// 2.3 section type
129-
sectionType, err := p.validateSectionType(record)
130-
if err != nil {
131-
return ColumnDTO{}, err
132-
}
61+
sectionType := strings.TrimPrefix(record.GetSectionType().String(), "SEC_")
13362
// 4. check if the key is empty, if so, return an error
13463
key := record.GetColumnKey()
13564
if key == "" {
13665
return ColumnDTO{}, errors.New("column key cannot be EMPTY")
13766
}
13867
// 5. check the metric color length, if it is not empty, it must be 2 elements
139-
if len(record.GetMetricColor()) > 0 && len(record.GetMetricColor()) != 2 {
68+
if record.GetMetricColor() != nil && len(record.GetMetricColor()) > 0 && len(record.GetMetricColor()) != 2 {
14069
return ColumnDTO{}, errors.New("metric color must be empty or have exactly 2 elements")
14170
}
14271
return ColumnDTO{
143-
Class: class,
72+
Class: columnClass,
14473
Type: columnType,
14574
Key: record.GetColumnKey(),
14675
Name: record.GetColumnName(),

0 commit comments

Comments
 (0)