forked from ebhomengo/niki
1
0
Fork 0
niki/vendor/github.com/brianvoe/gofakeit/v6/helpers.go

688 lines
8.9 KiB
Go
Raw Normal View History

2024-04-26 19:30:35 +00:00
package gofakeit
import (
crand "crypto/rand"
"encoding/binary"
"encoding/json"
"fmt"
"math"
"math/rand"
"reflect"
"strings"
"unicode"
"github.com/brianvoe/gofakeit/v6/data"
)
const lowerStr = "abcdefghijklmnopqrstuvwxyz"
2024-04-26 19:30:35 +00:00
const upperStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
2024-04-26 19:30:35 +00:00
const numericStr = "0123456789"
2024-04-26 19:30:35 +00:00
const specialStr = "@#$%&?|!(){}<>=*+-_:;,."
2024-04-26 19:30:35 +00:00
const specialSafeStr = "@#$&?!-_*."
2024-04-26 19:30:35 +00:00
const spaceStr = " "
2024-04-26 19:30:35 +00:00
const allStr = lowerStr + upperStr + numericStr + specialStr + spaceStr
2024-04-26 19:30:35 +00:00
const vowels = "aeiou"
2024-04-26 19:30:35 +00:00
const hashtag = '#'
2024-04-26 19:30:35 +00:00
const questionmark = '?'
2024-04-26 19:30:35 +00:00
const dash = '-'
2024-04-26 19:30:35 +00:00
const base58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
2024-04-26 19:30:35 +00:00
const minUint = 0
2024-04-26 19:30:35 +00:00
const maxUint = ^uint(0)
2024-04-26 19:30:35 +00:00
const minInt = -maxInt - 1
2024-04-26 19:30:35 +00:00
const maxInt = int(^uint(0) >> 1)
// Seed will set the global random value. Setting seed to 0 will use crypto/rand
2024-04-26 19:30:35 +00:00
func Seed(seed int64) {
2024-04-26 19:30:35 +00:00
if seed == 0 {
2024-04-26 19:30:35 +00:00
binary.Read(crand.Reader, binary.BigEndian, &seed)
2024-04-26 19:30:35 +00:00
globalFaker.Rand.Seed(seed)
2024-04-26 19:30:35 +00:00
} else {
2024-04-26 19:30:35 +00:00
globalFaker.Rand.Seed(seed)
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
// Check if in lib
2024-04-26 19:30:35 +00:00
func dataCheck(dataVal []string) bool {
2024-04-26 19:30:35 +00:00
var checkOk bool
if len(dataVal) == 2 {
2024-04-26 19:30:35 +00:00
_, checkOk = data.Data[dataVal[0]]
2024-04-26 19:30:35 +00:00
if checkOk {
2024-04-26 19:30:35 +00:00
_, checkOk = data.Data[dataVal[0]][dataVal[1]]
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
return checkOk
2024-04-26 19:30:35 +00:00
}
// Get Random Value
2024-04-26 19:30:35 +00:00
func getRandValue(r *rand.Rand, dataVal []string) string {
2024-04-26 19:30:35 +00:00
if !dataCheck(dataVal) {
2024-04-26 19:30:35 +00:00
return ""
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
return data.Data[dataVal[0]][dataVal[1]][r.Intn(len(data.Data[dataVal[0]][dataVal[1]]))]
2024-04-26 19:30:35 +00:00
}
// Replace # with numbers
2024-04-26 19:30:35 +00:00
func replaceWithNumbers(r *rand.Rand, str string) string {
2024-04-26 19:30:35 +00:00
if str == "" {
2024-04-26 19:30:35 +00:00
return str
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
bytestr := []byte(str)
2024-04-26 19:30:35 +00:00
for i := 0; i < len(bytestr); i++ {
2024-04-26 19:30:35 +00:00
if bytestr[i] == hashtag {
2024-04-26 19:30:35 +00:00
bytestr[i] = byte(randDigit(r))
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
if bytestr[0] == '0' {
2024-04-26 19:30:35 +00:00
bytestr[0] = byte(r.Intn(8)+1) + '0'
2024-04-26 19:30:35 +00:00
}
return string(bytestr)
2024-04-26 19:30:35 +00:00
}
// Replace ? with ASCII lowercase letters
2024-04-26 19:30:35 +00:00
func replaceWithLetters(r *rand.Rand, str string) string {
2024-04-26 19:30:35 +00:00
if str == "" {
2024-04-26 19:30:35 +00:00
return str
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
bytestr := []byte(str)
2024-04-26 19:30:35 +00:00
for i := 0; i < len(bytestr); i++ {
2024-04-26 19:30:35 +00:00
if bytestr[i] == questionmark {
2024-04-26 19:30:35 +00:00
bytestr[i] = byte(randLetter(r))
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
return string(bytestr)
2024-04-26 19:30:35 +00:00
}
// Replace ? with ASCII lowercase letters between a and f
2024-04-26 19:30:35 +00:00
func replaceWithHexLetters(r *rand.Rand, str string) string {
2024-04-26 19:30:35 +00:00
if str == "" {
2024-04-26 19:30:35 +00:00
return str
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
bytestr := []byte(str)
2024-04-26 19:30:35 +00:00
for i := 0; i < len(bytestr); i++ {
2024-04-26 19:30:35 +00:00
if bytestr[i] == questionmark {
2024-04-26 19:30:35 +00:00
bytestr[i] = byte(randHexLetter(r))
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
return string(bytestr)
2024-04-26 19:30:35 +00:00
}
// Generate random lowercase ASCII letter
2024-04-26 19:30:35 +00:00
func randLetter(r *rand.Rand) rune {
2024-04-26 19:30:35 +00:00
allLetters := upperStr + lowerStr
2024-04-26 19:30:35 +00:00
return rune(allLetters[r.Intn(len(allLetters))])
2024-04-26 19:30:35 +00:00
}
func randCharacter(r *rand.Rand, s string) string {
2024-04-26 19:30:35 +00:00
return string(s[r.Int63()%int64(len(s))])
2024-04-26 19:30:35 +00:00
}
// Generate random lowercase ASCII letter between a and f
2024-04-26 19:30:35 +00:00
func randHexLetter(r *rand.Rand) rune {
2024-04-26 19:30:35 +00:00
return rune(byte(r.Intn(6)) + 'a')
2024-04-26 19:30:35 +00:00
}
// Generate random ASCII digit
2024-04-26 19:30:35 +00:00
func randDigit(r *rand.Rand) rune {
2024-04-26 19:30:35 +00:00
return rune(byte(r.Intn(10)) + '0')
2024-04-26 19:30:35 +00:00
}
// Generate random integer between min and max
2024-04-26 19:30:35 +00:00
func randIntRange(r *rand.Rand, min, max int) int {
2024-04-26 19:30:35 +00:00
// If they pass in the same number, just return that number
2024-04-26 19:30:35 +00:00
if min == max {
2024-04-26 19:30:35 +00:00
return min
2024-04-26 19:30:35 +00:00
}
// If they pass in a min that is bigger than max, swap them
2024-04-26 19:30:35 +00:00
if min > max {
2024-04-26 19:30:35 +00:00
ogmin := min
2024-04-26 19:30:35 +00:00
min = max
2024-04-26 19:30:35 +00:00
max = ogmin
2024-04-26 19:30:35 +00:00
}
// Figure out if the min/max numbers calculation
2024-04-26 19:30:35 +00:00
// would cause a panic in the Int63() function.
2024-04-26 19:30:35 +00:00
if max-min+1 > 0 {
2024-04-26 19:30:35 +00:00
return min + int(r.Int63n(int64(max-min+1)))
2024-04-26 19:30:35 +00:00
}
// Loop through the range until we find a number that fits
2024-04-26 19:30:35 +00:00
for {
2024-04-26 19:30:35 +00:00
v := int(r.Uint64())
2024-04-26 19:30:35 +00:00
if (v >= min) && (v <= max) {
2024-04-26 19:30:35 +00:00
return v
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
// Generate random uint between min and max
2024-04-26 19:30:35 +00:00
func randUintRange(r *rand.Rand, min, max uint) uint {
2024-04-26 19:30:35 +00:00
// If they pass in the same number, just return that number
2024-04-26 19:30:35 +00:00
if min == max {
2024-04-26 19:30:35 +00:00
return min
2024-04-26 19:30:35 +00:00
}
// If they pass in a min that is bigger than max, swap them
2024-04-26 19:30:35 +00:00
if min > max {
2024-04-26 19:30:35 +00:00
ogmin := min
2024-04-26 19:30:35 +00:00
min = max
2024-04-26 19:30:35 +00:00
max = ogmin
2024-04-26 19:30:35 +00:00
}
// Figure out if the min/max numbers calculation
2024-04-26 19:30:35 +00:00
// would cause a panic in the Int63() function.
2024-04-26 19:30:35 +00:00
if int(max)-int(min)+1 > 0 {
2024-04-26 19:30:35 +00:00
return uint(r.Intn(int(max)-int(min)+1) + int(min))
2024-04-26 19:30:35 +00:00
}
// Loop through the range until we find a number that fits
2024-04-26 19:30:35 +00:00
for {
2024-04-26 19:30:35 +00:00
v := uint(r.Uint64())
2024-04-26 19:30:35 +00:00
if (v >= min) && (v <= max) {
2024-04-26 19:30:35 +00:00
return v
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
func toFixed(num float64, precision int) float64 {
2024-04-26 19:30:35 +00:00
output := math.Pow(10, float64(precision))
2024-04-26 19:30:35 +00:00
return float64(math.Floor(num*output)) / output
2024-04-26 19:30:35 +00:00
}
func equalSliceString(a, b []string) bool {
2024-04-26 19:30:35 +00:00
sizeA, sizeB := len(a), len(b)
2024-04-26 19:30:35 +00:00
if sizeA != sizeB {
2024-04-26 19:30:35 +00:00
return false
2024-04-26 19:30:35 +00:00
}
for i, va := range a {
2024-04-26 19:30:35 +00:00
vb := b[i]
if va != vb {
2024-04-26 19:30:35 +00:00
return false
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
return true
2024-04-26 19:30:35 +00:00
}
func equalSliceInt(a, b []int) bool {
2024-04-26 19:30:35 +00:00
sizeA, sizeB := len(a), len(b)
2024-04-26 19:30:35 +00:00
if sizeA != sizeB {
2024-04-26 19:30:35 +00:00
return false
2024-04-26 19:30:35 +00:00
}
for i, va := range a {
2024-04-26 19:30:35 +00:00
vb := b[i]
if va != vb {
2024-04-26 19:30:35 +00:00
return false
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
return true
2024-04-26 19:30:35 +00:00
}
func equalSliceInterface(a, b []any) bool {
2024-04-26 19:30:35 +00:00
sizeA, sizeB := len(a), len(b)
2024-04-26 19:30:35 +00:00
if sizeA != sizeB {
2024-04-26 19:30:35 +00:00
return false
2024-04-26 19:30:35 +00:00
}
for i, va := range a {
2024-04-26 19:30:35 +00:00
if !reflect.DeepEqual(va, b[i]) {
2024-04-26 19:30:35 +00:00
return false
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
return true
2024-04-26 19:30:35 +00:00
}
func stringInSlice(a string, list []string) bool {
2024-04-26 19:30:35 +00:00
for _, b := range list {
2024-04-26 19:30:35 +00:00
if b == a {
2024-04-26 19:30:35 +00:00
return true
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
return false
2024-04-26 19:30:35 +00:00
}
func anyToString(a any) string {
2024-04-26 19:30:35 +00:00
if a == nil {
2024-04-26 19:30:35 +00:00
return ""
2024-04-26 19:30:35 +00:00
}
// If it's a slice of bytes or struct, unmarshal it into an interface
2024-04-26 19:30:35 +00:00
if bytes, ok := a.([]byte); ok {
2024-04-26 19:30:35 +00:00
return string(bytes)
2024-04-26 19:30:35 +00:00
}
// If it's a struct, map, or slice, convert to JSON
2024-04-26 19:30:35 +00:00
switch reflect.TypeOf(a).Kind() {
2024-04-26 19:30:35 +00:00
case reflect.Struct, reflect.Map, reflect.Slice:
2024-04-26 19:30:35 +00:00
b, err := json.Marshal(a)
2024-04-26 19:30:35 +00:00
if err == nil {
2024-04-26 19:30:35 +00:00
return string(b)
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
return fmt.Sprintf("%v", a)
2024-04-26 19:30:35 +00:00
}
// Title returns a copy of the string s with all Unicode letters that begin words
2024-04-26 19:30:35 +00:00
// mapped to their Unicode title case
2024-04-26 19:30:35 +00:00
func title(s string) string {
2024-04-26 19:30:35 +00:00
// isSeparator reports whether the rune could mark a word boundary
2024-04-26 19:30:35 +00:00
isSeparator := func(r rune) bool {
2024-04-26 19:30:35 +00:00
// ASCII alphanumerics and underscore are not separators
2024-04-26 19:30:35 +00:00
if r <= 0x7F {
2024-04-26 19:30:35 +00:00
switch {
2024-04-26 19:30:35 +00:00
case '0' <= r && r <= '9':
2024-04-26 19:30:35 +00:00
return false
2024-04-26 19:30:35 +00:00
case 'a' <= r && r <= 'z':
2024-04-26 19:30:35 +00:00
return false
2024-04-26 19:30:35 +00:00
case 'A' <= r && r <= 'Z':
2024-04-26 19:30:35 +00:00
return false
2024-04-26 19:30:35 +00:00
case r == '_':
2024-04-26 19:30:35 +00:00
return false
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
return true
2024-04-26 19:30:35 +00:00
}
// Letters and digits are not separators
2024-04-26 19:30:35 +00:00
if unicode.IsLetter(r) || unicode.IsDigit(r) {
2024-04-26 19:30:35 +00:00
return false
2024-04-26 19:30:35 +00:00
}
// Otherwise, all we can do for now is treat spaces as separators.
2024-04-26 19:30:35 +00:00
return unicode.IsSpace(r)
2024-04-26 19:30:35 +00:00
}
prev := ' '
2024-04-26 19:30:35 +00:00
return strings.Map(
2024-04-26 19:30:35 +00:00
func(r rune) rune {
2024-04-26 19:30:35 +00:00
if isSeparator(prev) {
2024-04-26 19:30:35 +00:00
prev = r
2024-04-26 19:30:35 +00:00
return unicode.ToTitle(r)
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
prev = r
2024-04-26 19:30:35 +00:00
return r
2024-04-26 19:30:35 +00:00
},
2024-04-26 19:30:35 +00:00
s)
2024-04-26 19:30:35 +00:00
}
func funcLookupSplit(str string) []string {
2024-04-26 19:30:35 +00:00
out := []string{}
2024-04-26 19:30:35 +00:00
for str != "" {
2024-04-26 19:30:35 +00:00
if strings.HasPrefix(str, "[") {
2024-04-26 19:30:35 +00:00
startIndex := strings.Index(str, "[")
2024-04-26 19:30:35 +00:00
endIndex := strings.Index(str, "]")
2024-04-26 19:30:35 +00:00
val := str[(startIndex) : endIndex+1]
2024-04-26 19:30:35 +00:00
out = append(out, strings.TrimSpace(val))
2024-04-26 19:30:35 +00:00
str = strings.Replace(str, val, "", 1)
// Trim off comma if it has it
2024-04-26 19:30:35 +00:00
if strings.HasPrefix(str, ",") {
2024-04-26 19:30:35 +00:00
str = strings.Replace(str, ",", "", 1)
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
} else {
2024-04-26 19:30:35 +00:00
strSplit := strings.SplitN(str, ",", 2)
2024-04-26 19:30:35 +00:00
strSplitLen := len(strSplit)
2024-04-26 19:30:35 +00:00
if strSplitLen >= 1 {
2024-04-26 19:30:35 +00:00
out = append(out, strings.TrimSpace(strSplit[0]))
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
if strSplitLen >= 2 {
2024-04-26 19:30:35 +00:00
str = strSplit[1]
2024-04-26 19:30:35 +00:00
} else {
2024-04-26 19:30:35 +00:00
str = ""
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
return out
2024-04-26 19:30:35 +00:00
}
// Used for parsing the tag in a struct
2024-04-26 19:30:35 +00:00
func parseNameAndParamsFromTag(tag string) (string, string) {
2024-04-26 19:30:35 +00:00
// Trim the curly on the beginning and end
2024-04-26 19:30:35 +00:00
tag = strings.TrimLeft(tag, "{")
2024-04-26 19:30:35 +00:00
tag = strings.TrimRight(tag, "}")
2024-04-26 19:30:35 +00:00
// Check if has params separated by :
2024-04-26 19:30:35 +00:00
fNameSplit := strings.SplitN(tag, ":", 2)
2024-04-26 19:30:35 +00:00
fName := ""
2024-04-26 19:30:35 +00:00
fParams := ""
2024-04-26 19:30:35 +00:00
if len(fNameSplit) >= 1 {
2024-04-26 19:30:35 +00:00
fName = fNameSplit[0]
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
if len(fNameSplit) >= 2 {
2024-04-26 19:30:35 +00:00
fParams = fNameSplit[1]
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
return fName, fParams
2024-04-26 19:30:35 +00:00
}
// Used for parsing map params
2024-04-26 19:30:35 +00:00
func parseMapParams(info *Info, fParams string) *MapParams {
2024-04-26 19:30:35 +00:00
// Get parameters, make sure params and the split both have values
2024-04-26 19:30:35 +00:00
mapParams := NewMapParams()
2024-04-26 19:30:35 +00:00
paramsLen := len(info.Params)
// If just one param and its a string simply just pass it
2024-04-26 19:30:35 +00:00
if paramsLen == 1 && info.Params[0].Type == "string" {
2024-04-26 19:30:35 +00:00
mapParams.Add(info.Params[0].Field, fParams)
2024-04-26 19:30:35 +00:00
} else if paramsLen > 0 && fParams != "" {
2024-04-26 19:30:35 +00:00
splitVals := funcLookupSplit(fParams)
2024-04-26 19:30:35 +00:00
mapParams = addSplitValsToMapParams(splitVals, info, mapParams)
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
if mapParams.Size() > 0 {
2024-04-26 19:30:35 +00:00
return mapParams
2024-04-26 19:30:35 +00:00
} else {
2024-04-26 19:30:35 +00:00
return nil
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
// Used for splitting the values
2024-04-26 19:30:35 +00:00
func addSplitValsToMapParams(splitVals []string, info *Info, mapParams *MapParams) *MapParams {
2024-04-26 19:30:35 +00:00
for ii := 0; ii < len(splitVals); ii++ {
2024-04-26 19:30:35 +00:00
if len(info.Params)-1 >= ii {
2024-04-26 19:30:35 +00:00
if strings.HasPrefix(splitVals[ii], "[") {
2024-04-26 19:30:35 +00:00
lookupSplits := funcLookupSplit(strings.TrimRight(strings.TrimLeft(splitVals[ii], "["), "]"))
2024-04-26 19:30:35 +00:00
for _, v := range lookupSplits {
2024-04-26 19:30:35 +00:00
mapParams.Add(info.Params[ii].Field, v)
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
} else {
2024-04-26 19:30:35 +00:00
mapParams.Add(info.Params[ii].Field, splitVals[ii])
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
return mapParams
2024-04-26 19:30:35 +00:00
}