-
Notifications
You must be signed in to change notification settings - Fork 1
/
lenstring.go
147 lines (132 loc) · 3.46 KB
/
lenstring.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package types
import (
"bytes"
"encoding/json"
"errors"
"fmt"
)
// LenString holds a string together with a minimum and maximum length.
// Validate returns an error if the string length does not fit the minium-maxium length.
// LenString implements the encoding.UnmarshalText, json.Unmarshaler,
// and strfmt.StringAssignable interfaces that will do length validation.
type LenString struct {
str string
min int
max int
}
// NewLenString returns a new LenString without validating it.
func NewLenString(str string, min, max int) *LenString {
return &LenString{
str: str,
min: min,
max: max,
}
}
// MustLenString returns a LenString or panics on errors from Validate.
func MustLenString(str string, min, max int) LenString {
s := LenString{
str: str,
min: min,
max: max,
}
err := s.Validate()
if err != nil {
panic(err)
}
return s
}
// Validate implements the ValidatErr interface
func (s *LenString) Validate() error {
if s == nil {
return errors.New("nil LenString")
}
if s.min < 0 {
return fmt.Errorf("negative minimum length %d of LenString %q", s.min, s.str)
}
if s.max < 0 {
return fmt.Errorf("negative maximum length %d of LenString %q", s.max, s.str)
}
if s.min > s.max {
return fmt.Errorf("minimum length %d is greater than maximum length %d of LenString %q", s.min, s.max, s.str)
}
return s.validateLen(s.str)
}
func (s *LenString) validateLen(str string) error {
l := len(str)
if l < s.min {
return fmt.Errorf("length %d of LenString %q is shorter than minimum of %d", l, str, s.min)
}
if l > s.max {
return fmt.Errorf("length %d of LenString %q is longer than maximum of %d", l, str, s.max)
}
return nil
}
// String returns the string or "<nil>".
// String implements the fmt.Stringer interface.
func (s *LenString) String() string {
if s == nil {
return "<nil>"
}
return s.str
}
func (s *LenString) SetString(str string) error {
if err := s.validateLen(str); err != nil {
return err
}
s.str = str
return nil
}
func (s *LenString) MinLen() int {
return s.min
}
func (s *LenString) MaxLen() int {
return s.max
}
// MarshalText implements the encoding.TextMarshaler interface
func (s *LenString) MarshalText() (text []byte, err error) {
if s == nil {
return nil, nil
}
return []byte(s.str), nil
}
// UnmarshalText implements the encoding.TextUnmarshaler interface
func (s *LenString) UnmarshalText(text []byte) error {
return s.SetString(string(text))
}
// MarshalText implements the json.Marshaler interface
func (s *LenString) MarshalJSON() (text []byte, err error) {
if s == nil {
return []byte("null"), nil
}
return json.Marshal(s.str)
}
// UnmarshalJSON implements the json.Unmarshaler interface
func (s *LenString) UnmarshalJSON(text []byte) error {
if bytes.Equal(text, []byte("null")) {
return nil // no-op
}
var str string
err := json.Unmarshal(text, &s.str)
if err != nil {
return fmt.Errorf("can't unmarshal JSON to LenString because of: %w", err)
}
return s.SetString(str)
}
// ScanString tries to parse and assign the passed
// source string as value of the implementing type.
//
// If validate is true, the source string is checked
// for validity before it is assigned to the type.
//
// If validate is false and the source string
// can still be assigned in some non-normalized way
// it will be assigned without returning an error.
func (s *LenString) ScanString(source string, validate bool) error {
if validate {
if err := s.validateLen(source); err != nil {
return err
}
}
s.str = source
return nil
}