...
1 package ordering
2
3 import (
4 "fmt"
5 "strconv"
6 "strings"
7 "unicode"
8
9 "go.einride.tech/aip/fieldmask"
10 "google.golang.org/protobuf/proto"
11 "google.golang.org/protobuf/types/known/fieldmaskpb"
12 )
13
14
15 type OrderBy struct {
16
17 Fields []Field
18 }
19
20
21 type Field struct {
22
23 Path string
24
25 Desc bool
26 }
27
28
29
30
31 func (f Field) SubFields() []string {
32 if f.Path == "" {
33 return nil
34 }
35 return strings.Split(f.Path, ".")
36 }
37
38
39 func (o *OrderBy) UnmarshalString(s string) error {
40 o.Fields = o.Fields[:0]
41 if s == "" {
42 return nil
43 }
44 for _, r := range s {
45 if !unicode.IsLetter(r) && !unicode.IsNumber(r) && r != '_' && r != ' ' && r != ',' && r != '.' {
46 return fmt.Errorf("unmarshal order by '%s': invalid character %s", s, strconv.QuoteRune(r))
47 }
48 }
49 fields := strings.Split(s, ",")
50 o.Fields = make([]Field, 0, len(fields))
51 for _, field := range fields {
52 parts := strings.Fields(field)
53 switch len(parts) {
54 case 1:
55 o.Fields = append(o.Fields, Field{Path: parts[0]})
56 case 2:
57 order := parts[1]
58 var desc bool
59 switch order {
60 case "asc":
61 desc = false
62 case "desc":
63 desc = true
64 default:
65 return fmt.Errorf("unmarshal order by '%s': invalid format", s)
66 }
67 o.Fields = append(o.Fields, Field{Path: parts[0], Desc: desc})
68 case 0:
69 fallthrough
70 default:
71 return fmt.Errorf("unmarshal order by '%s': invalid format", s)
72 }
73 }
74 return nil
75 }
76
77
78
79 func (o OrderBy) ValidateForMessage(m proto.Message) error {
80 fm := fieldmaskpb.FieldMask{
81 Paths: make([]string, 0, len(o.Fields)),
82 }
83 for _, field := range o.Fields {
84 fm.Paths = append(fm.Paths, field.Path)
85 }
86 return fieldmask.Validate(&fm, m)
87 }
88
89
90 func (o OrderBy) ValidateForPaths(paths ...string) error {
91 FieldLoop:
92 for _, field := range o.Fields {
93
94 for _, path := range paths {
95 if field.Path == path {
96 continue FieldLoop
97 }
98 }
99 return fmt.Errorf("invalid field path: %s", field.Path)
100 }
101 return nil
102 }
103
View as plain text