This repository has been archived by the owner on Sep 13, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfaker.go
282 lines (251 loc) · 6.31 KB
/
faker.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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
package faker
import (
crand "crypto/rand"
"encoding/binary"
"fmt"
"math/rand"
"strconv"
"strings"
)
// Faker is Faker instance
type Faker struct {
cfg *Config
}
// New returns a new Faker instance with options
//
// faker.New(
// faker.WithRand(rand.New(rand.NewSource(time.Now().Unix()))),
// faker.WithColors("", ""),
// faker.WithHexSymbols(""),
// faker.WithWeekdays("", ""),
// faker.WithMonths("", ""),
// faker.WithPasswordMin(0),
// faker.WithPasswordMax(0),
// faker.WithPasswordChars(""),
// faker.WithGenericTopLevelDomains("", ""),
// faker.WithFirstNames("", ""),
// faker.WithLastNames("", ""),
// )
//
func New(opts ...Option) *Faker {
cfg := newConfig(opts...)
return &Faker{cfg: cfg}
}
type (
// Config -.
Config struct {
rand *rand.Rand
// Unicode characters as integers
asciifyUnicodeDecimals []int
// Address
postCodeFormats []string
// Auth
passwordMin int
passwordMax int
passwordChars string
// Color
colors []string
hexSymbols string
// Date
weekdays []string
months []string
// Internet
genericTopLevelDomains []string
httpMethods []string
httpStatusCodes []int
// Person
firstNames []string
lastNames []string
}
// Option -.
Option func(opts *Config)
)
// WithRand -.
func WithRand(r *rand.Rand) Option {
return func(cfg *Config) {
cfg.rand = r
}
}
// WithAsciifyUnicodeDecimals -.
func WithAsciifyUnicodeDecimals(asciifyUnicodeDecimals ...int) Option {
return func(cfg *Config) {
cfg.asciifyUnicodeDecimals = asciifyUnicodeDecimals
}
}
// WithPostCodeFormats -.
func WithPostCodeFormats(postCodeFormats ...string) Option {
return func(cfg *Config) {
cfg.postCodeFormats = postCodeFormats
}
}
// WithColors -.
func WithColors(colors ...string) Option {
return func(cfg *Config) {
cfg.colors = colors
}
}
// WithHexSymbols -.
func WithHexSymbols(hexSymbols string) Option {
return func(cfg *Config) {
cfg.hexSymbols = hexSymbols
}
}
// WithWeekdays -.
func WithWeekdays(weekdays ...string) Option {
return func(cfg *Config) {
cfg.weekdays = weekdays
}
}
// WithMonths -.
func WithMonths(months ...string) Option {
return func(cfg *Config) {
cfg.months = months
}
}
// WithPasswordMin -.
func WithPasswordMin(passwordMin int) Option {
return func(cfg *Config) {
cfg.passwordMin = passwordMin
}
}
// WithPasswordMax -.
func WithPasswordMax(passwordMax int) Option {
return func(cfg *Config) {
cfg.passwordMax = passwordMax
}
}
// WithPasswordChars -.
func WithPasswordChars(passwordChars string) Option {
return func(cfg *Config) {
cfg.passwordChars = passwordChars
}
}
// WithGenericTopLevelDomains -.
func WithGenericTopLevelDomains(genericTopLevelDomains ...string) Option {
return func(cfg *Config) {
cfg.genericTopLevelDomains = genericTopLevelDomains
}
}
// WithHTTPMethods -.
func WithHTTPMethods(httpMethods ...string) Option {
return func(cfg *Config) {
cfg.httpMethods = httpMethods
}
}
// WithHTTPStatusCodes -.
func WithHTTPStatusCodes(httpStatusCodes ...int) Option {
return func(cfg *Config) {
cfg.httpStatusCodes = httpStatusCodes
}
}
// WithFirstNames -.
func WithFirstNames(firstNames ...string) Option {
return func(cfg *Config) {
cfg.firstNames = firstNames
}
}
// WithLastNames -.
func WithLastNames(lastNames ...string) Option {
return func(cfg *Config) {
cfg.lastNames = lastNames
}
}
func newConfig(opts ...Option) *Config {
var cfg Config
for _, opt := range opts {
opt(&cfg)
}
if cfg.rand == nil {
var seed int64
if err := binary.Read(crand.Reader, binary.BigEndian, &seed); err != nil {
panic(err)
}
WithRand(rand.New(rand.NewSource(seed).(rand.Source64)))(&cfg)
}
return &cfg
}
// Integer returns a integer between a given minimum and maximum values
func (f *Faker) Integer(min, max int) int {
return Integer(min, max, WithRand(f.cfg.rand))
}
// Integer returns a int between a given minimum and maximum values
func Integer(min, max int, opts ...Option) int {
diff := max - min
if diff == 0 {
return min
}
cfg := newConfig(opts...)
return cfg.rand.Intn(diff) + min
}
// Number returns a float64 between a given minimum and maximum values
func (f *Faker) Number(min, max float64) float64 {
return Number(min, max, WithRand(f.cfg.rand))
}
// Number returns a float64 between a given minimum and maximum values
func Number(min, max float64, opts ...Option) float64 {
cfg := newConfig(opts...)
numbers := make([]float64, 10)
for i := range numbers {
numbers[i] = min + cfg.rand.Float64()*(max-min)
}
return RandomElement(numbers)
}
// RandomElement returns a random element from a given slice
func RandomElement[T any](slice []T, opts ...Option) T {
i := Integer(0, len(slice)-1, opts...)
return slice[i]
}
// Numerify returns a string that replace all "#" characters with numbers from 0 to 9 as string
func (f *Faker) Numerify(in string) string {
return Numerify(in, WithRand(f.cfg.rand))
}
// Numerify returns a string that replace all "#" characters with numbers from 0 to 9 as string
func Numerify(in string, opts ...Option) string {
var out strings.Builder
out.Grow(len(in))
for i := range in {
if in[i] == '#' {
out.WriteString(strconv.Itoa(Integer(0, 9, opts...)))
} else {
out.WriteByte(in[i])
}
}
return out.String()
}
// Asciify returns a string that replace all "*" characters with latin letters
func (f *Faker) Asciify(in string) string {
return Numerify(
in,
WithRand(f.cfg.rand),
WithAsciifyUnicodeDecimals(f.cfg.asciifyUnicodeDecimals...),
)
}
// Asciify returns a string that replace all "*" characters with unicode characters
func Asciify(in string, opts ...Option) string {
cfg := newConfig(opts...)
if len(cfg.asciifyUnicodeDecimals) == 0 {
latinLetters := make([]int, 0, 50)
// Capital letters
latinLetters = append(latinLetters, intArrRange(65, 90)...)
// Small letters
latinLetters = append(latinLetters, intArrRange(97, 122)...)
WithAsciifyUnicodeDecimals(latinLetters...)(cfg)
}
var out strings.Builder
out.Grow(len(in))
for i := range in {
if in[i] == '*' {
out.WriteString(fmt.Sprintf("%c", RandomElement(cfg.asciifyUnicodeDecimals, opts...)))
} else {
out.WriteByte(in[i])
}
}
return out.String()
}
func intArrRange(min, max int) []int {
arr := make([]int, max-min+1)
for i := range arr {
arr[i] = min + i
}
return arr
}