Skip to content

Commit

Permalink
Add max_rune_size and min_rune_size annotations to validate Chine…
Browse files Browse the repository at this point in the history
…se strings. (#35)

Co-authored-by: 王丽月 <[email protected]>
Co-authored-by: Li2CO3 <[email protected]>
  • Loading branch information
3 people authored Feb 8, 2025
1 parent c03b236 commit 4a18033
Show file tree
Hide file tree
Showing 9 changed files with 390 additions and 15 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@
# Dependency directories (remove the comment below to include it)
# vendor/
.vscode
.idea
22 changes: 12 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,18 @@ prefix `vt`, short for "validation"

### String/Binary

| Rule | |
| --------------- | -------------------------------- |
| vt.const | must be specified value |
| vt.pattern | regexp pattern |
| vt.prefix | prefix must be specified value |
| vt.suffix | suffix must be specified value |
| vt.contains | must contain specified value |
| vt.not_contains | must not contain specified value |
| vt.min_size | min size |
| vt.max_size | max size |
| Rule | |
|------------------|----------------------------------|
| vt.const | must be specified value |
| vt.pattern | regexp pattern |
| vt.prefix | prefix must be specified value |
| vt.suffix | suffix must be specified value |
| vt.contains | must contain specified value |
| vt.not_contains | must not contain specified value |
| vt.min_size | min size |
| vt.max_size | max size |
| vt.max_rune_size | max rune size |
| vt.min_rune_size | min rune size |

### Enum

Expand Down
2 changes: 2 additions & 0 deletions examples/rune_size/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
all:
thriftgo -g go -p validator test.thrift
282 changes: 282 additions & 0 deletions examples/rune_size/gen-go/test/test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
// Copyright 2021 CloudWeGo Authors
//
// 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 test

import (
"fmt"
"github.com/apache/thrift/lib/go/thrift"
)

type Example struct {
MaxRuneString string `thrift:"MaxRuneString,1" json:"MaxRuneString"`
MinRuneString string `thrift:"MinRuneString,2" json:"MinRuneString"`
KeyValues map[string]string `thrift:"KeyValues,3" json:"KeyValues"`
}

func NewExample() *Example {
return &Example{}
}

func (p *Example) InitDefault() {
}

func (p *Example) GetMaxRuneString() (v string) {
return p.MaxRuneString
}

func (p *Example) GetMinRuneString() (v string) {
return p.MinRuneString
}

func (p *Example) GetKeyValues() (v map[string]string) {
return p.KeyValues
}

var fieldIDToName_Example = map[int16]string{
1: "MaxRuneString",
2: "MinRuneString",
3: "KeyValues",
}

func (p *Example) Read(iprot thrift.TProtocol) (err error) {

var fieldTypeId thrift.TType
var fieldId int16

if _, err = iprot.ReadStructBegin(); err != nil {
goto ReadStructBeginError
}

for {
_, fieldTypeId, fieldId, err = iprot.ReadFieldBegin()
if err != nil {
goto ReadFieldBeginError
}
if fieldTypeId == thrift.STOP {
break
}

switch fieldId {
case 1:
if fieldTypeId == thrift.STRING {
if err = p.ReadField1(iprot); err != nil {
goto ReadFieldError
}
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
case 2:
if fieldTypeId == thrift.STRING {
if err = p.ReadField2(iprot); err != nil {
goto ReadFieldError
}
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
case 3:
if fieldTypeId == thrift.MAP {
if err = p.ReadField3(iprot); err != nil {
goto ReadFieldError
}
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
default:
if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
}
if err = iprot.ReadFieldEnd(); err != nil {
goto ReadFieldEndError
}
}
if err = iprot.ReadStructEnd(); err != nil {
goto ReadStructEndError
}

return nil
ReadStructBeginError:
return thrift.PrependError(fmt.Sprintf("%T read struct begin error: ", p), err)
ReadFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err)
ReadFieldError:
return thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_Example[fieldId]), err)
SkipFieldError:
return thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err)

ReadFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T read field end error", p), err)
ReadStructEndError:
return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
}

func (p *Example) ReadField1(iprot thrift.TProtocol) error {

var _field string
if v, err := iprot.ReadString(); err != nil {
return err
} else {
_field = v
}
p.MaxRuneString = _field
return nil
}
func (p *Example) ReadField2(iprot thrift.TProtocol) error {

var _field string
if v, err := iprot.ReadString(); err != nil {
return err
} else {
_field = v
}
p.MinRuneString = _field
return nil
}
func (p *Example) ReadField3(iprot thrift.TProtocol) error {
_, _, size, err := iprot.ReadMapBegin()
if err != nil {
return err
}
_field := make(map[string]string, size)
for i := 0; i < size; i++ {
var _key string
if v, err := iprot.ReadString(); err != nil {
return err
} else {
_key = v
}

var _val string
if v, err := iprot.ReadString(); err != nil {
return err
} else {
_val = v
}

_field[_key] = _val
}
if err := iprot.ReadMapEnd(); err != nil {
return err
}
p.KeyValues = _field
return nil
}

func (p *Example) Write(oprot thrift.TProtocol) (err error) {

var fieldId int16
if err = oprot.WriteStructBegin("Example"); err != nil {
goto WriteStructBeginError
}
if p != nil {
if err = p.writeField1(oprot); err != nil {
fieldId = 1
goto WriteFieldError
}
if err = p.writeField2(oprot); err != nil {
fieldId = 2
goto WriteFieldError
}
if err = p.writeField3(oprot); err != nil {
fieldId = 3
goto WriteFieldError
}
}
if err = oprot.WriteFieldStop(); err != nil {
goto WriteFieldStopError
}
if err = oprot.WriteStructEnd(); err != nil {
goto WriteStructEndError
}
return nil
WriteStructBeginError:
return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
WriteFieldError:
return thrift.PrependError(fmt.Sprintf("%T write field %d error: ", p, fieldId), err)
WriteFieldStopError:
return thrift.PrependError(fmt.Sprintf("%T write field stop error: ", p), err)
WriteStructEndError:
return thrift.PrependError(fmt.Sprintf("%T write struct end error: ", p), err)
}

func (p *Example) writeField1(oprot thrift.TProtocol) (err error) {
if err = oprot.WriteFieldBegin("MaxRuneString", thrift.STRING, 1); err != nil {
goto WriteFieldBeginError
}
if err := oprot.WriteString(p.MaxRuneString); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 1 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 1 end error: ", p), err)
}

func (p *Example) writeField2(oprot thrift.TProtocol) (err error) {
if err = oprot.WriteFieldBegin("MinRuneString", thrift.STRING, 2); err != nil {
goto WriteFieldBeginError
}
if err := oprot.WriteString(p.MinRuneString); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 2 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 2 end error: ", p), err)
}

func (p *Example) writeField3(oprot thrift.TProtocol) (err error) {
if err = oprot.WriteFieldBegin("KeyValues", thrift.MAP, 3); err != nil {
goto WriteFieldBeginError
}
if err := oprot.WriteMapBegin(thrift.STRING, thrift.STRING, len(p.KeyValues)); err != nil {
return err
}
for k, v := range p.KeyValues {
if err := oprot.WriteString(k); err != nil {
return err
}
if err := oprot.WriteString(v); err != nil {
return err
}
}
if err := oprot.WriteMapEnd(); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 3 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 3 end error: ", p), err)
}

func (p *Example) String() string {
if p == nil {
return "<nil>"
}
return fmt.Sprintf("Example(%+v)", *p)

}
52 changes: 52 additions & 0 deletions examples/rune_size/gen-go/test/test_validator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright 2021 CloudWeGo Authors
//
// 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 test

import (
"bytes"
"fmt"
"reflect"
"regexp"
"strings"
"time"
)

// unused protection
var (
_ = fmt.Formatter(nil)
_ = (*bytes.Buffer)(nil)
_ = (*strings.Builder)(nil)
_ = reflect.Type(nil)
_ = (*regexp.Regexp)(nil)
_ = time.Nanosecond
)

func (p *Example) IsValid() error {
if len([]rune(p.MaxRuneString)) > int(10) {
return fmt.Errorf("field MaxRuneString max_rune_size rule failed, current value: %d", len([]rune(p.MaxRuneString)))
}
if len([]rune(p.MinRuneString)) < int(10) {
return fmt.Errorf("field MinRuneString min_rune_size rule failed, current value: %d", len([]rune(p.MinRuneString)))
}
for k := range p.KeyValues {
if len([]rune(k)) > int(10) {
return fmt.Errorf("field k max_rune_size rule failed, current value: %d", len([]rune(k)))
}
if len([]rune(k)) < int(10) {
return fmt.Errorf("field k min_rune_size rule failed, current value: %d", len([]rune(k)))
}
}
return nil
}
5 changes: 5 additions & 0 deletions examples/rune_size/test.thrift
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
struct Example {
1: string MaxRuneString (vt.max_rune_size = "10") // rune length of MaxRuneString should be less than or equal to 10
2: string MinRuneString (vt.min_rune_size = "10") // rune length of MinRuneString should be greater than or equal to 10
3: map<string, string> KeyValues (vt.key.max_rune_size = "10" vt.key.min_rune_size = "10") // rune length of KeyValues' key must be equal to 10
}
Loading

0 comments on commit 4a18033

Please sign in to comment.