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

1020 lines
16 KiB
Go
Raw Normal View History

2024-04-26 19:30:35 +00:00
package gofakeit
import (
"encoding/json"
"errors"
"fmt"
"math"
"math/rand"
"regexp/syntax"
"strings"
)
// Generate fake information from given string.
2024-04-26 19:30:35 +00:00
// Replaceable values should be within {}
2024-04-26 19:30:35 +00:00
//
2024-04-26 19:30:35 +00:00
// Functions
2024-04-26 19:30:35 +00:00
// Ex: {firstname} - billy
2024-04-26 19:30:35 +00:00
// Ex: {sentence:3} - Record river mind.
2024-04-26 19:30:35 +00:00
// Ex: {number:1,10} - 4
2024-04-26 19:30:35 +00:00
// Ex: {uuid} - 590c1440-9888-45b0-bd51-a817ee07c3f2
2024-04-26 19:30:35 +00:00
//
2024-04-26 19:30:35 +00:00
// Letters/Numbers
2024-04-26 19:30:35 +00:00
// Ex: ### - 481 - random numbers
2024-04-26 19:30:35 +00:00
// Ex: ??? - fda - random letters
2024-04-26 19:30:35 +00:00
//
2024-04-26 19:30:35 +00:00
// For a complete list of runnable functions use FuncsLookup
2024-04-26 19:30:35 +00:00
func Generate(dataVal string) string { return generate(globalFaker.Rand, dataVal) }
// Generate fake information from given string.
2024-04-26 19:30:35 +00:00
// Replaceable values should be within {}
2024-04-26 19:30:35 +00:00
//
2024-04-26 19:30:35 +00:00
// Functions
2024-04-26 19:30:35 +00:00
// Ex: {firstname} - billy
2024-04-26 19:30:35 +00:00
// Ex: {sentence:3} - Record river mind.
2024-04-26 19:30:35 +00:00
// Ex: {number:1,10} - 4
2024-04-26 19:30:35 +00:00
// Ex: {uuid} - 590c1440-9888-45b0-bd51-a817ee07c3f2
2024-04-26 19:30:35 +00:00
//
2024-04-26 19:30:35 +00:00
// Letters/Numbers
2024-04-26 19:30:35 +00:00
// Ex: ### - 481 - random numbers
2024-04-26 19:30:35 +00:00
// Ex: ??? - fda - random letters
2024-04-26 19:30:35 +00:00
//
2024-04-26 19:30:35 +00:00
// For a complete list of runnable functions use FuncsLookup
2024-04-26 19:30:35 +00:00
func (f *Faker) Generate(dataVal string) string { return generate(f.Rand, dataVal) }
func generate(r *rand.Rand, dataVal string) string {
2024-04-26 19:30:35 +00:00
// Replace # with numbers and ? with letters
2024-04-26 19:30:35 +00:00
dataVal = replaceWithNumbers(r, dataVal)
2024-04-26 19:30:35 +00:00
dataVal = replaceWithLetters(r, dataVal)
// Check if string has any replaceable values
2024-04-26 19:30:35 +00:00
if !strings.Contains(dataVal, "{") && !strings.Contains(dataVal, "}") {
2024-04-26 19:30:35 +00:00
return dataVal
2024-04-26 19:30:35 +00:00
}
// Variables to identify the index in which it exists
2024-04-26 19:30:35 +00:00
startCurly := -1
2024-04-26 19:30:35 +00:00
startCurlyIgnore := []int{}
2024-04-26 19:30:35 +00:00
endCurly := -1
2024-04-26 19:30:35 +00:00
endCurlyIgnore := []int{}
// Loop through string characters
2024-04-26 19:30:35 +00:00
for i := 0; i < len(dataVal); i++ {
2024-04-26 19:30:35 +00:00
// Check for ignores if equal skip
2024-04-26 19:30:35 +00:00
shouldSkip := false
2024-04-26 19:30:35 +00:00
for _, igs := range startCurlyIgnore {
2024-04-26 19:30:35 +00:00
if i == igs {
2024-04-26 19:30:35 +00:00
shouldSkip = 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
for _, ige := range endCurlyIgnore {
2024-04-26 19:30:35 +00:00
if i == ige {
2024-04-26 19:30:35 +00:00
shouldSkip = 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
if shouldSkip {
2024-04-26 19:30:35 +00:00
continue
2024-04-26 19:30:35 +00:00
}
// Identify items between brackets. Ex: {firstname}
2024-04-26 19:30:35 +00:00
if string(dataVal[i]) == "{" {
2024-04-26 19:30:35 +00:00
startCurly = i
2024-04-26 19:30:35 +00:00
continue
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
if startCurly != -1 && string(dataVal[i]) == "}" {
2024-04-26 19:30:35 +00:00
endCurly = i
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
if startCurly == -1 || endCurly == -1 {
2024-04-26 19:30:35 +00:00
continue
2024-04-26 19:30:35 +00:00
}
// Get the value between brackets
2024-04-26 19:30:35 +00:00
fParts := dataVal[startCurly+1 : endCurly]
// Check if has params separated by :
2024-04-26 19:30:35 +00:00
fNameSplit := strings.SplitN(fParts, ":", 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
}
// Check to see if its a replaceable lookup function
2024-04-26 19:30:35 +00:00
if info := GetFuncLookup(fName); info != nil {
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
mapParams = nil
2024-04-26 19:30:35 +00:00
}
// Call function
2024-04-26 19:30:35 +00:00
fValue, err := info.Generate(r, mapParams, info)
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
// If we came across an error just dont replace value
2024-04-26 19:30:35 +00:00
dataVal = strings.Replace(dataVal, "{"+fParts+"}", err.Error(), 1)
2024-04-26 19:30:35 +00:00
} else {
2024-04-26 19:30:35 +00:00
// Successfully found, run replace with new value
2024-04-26 19:30:35 +00:00
dataVal = strings.Replace(dataVal, "{"+fParts+"}", fmt.Sprintf("%v", fValue), 1)
2024-04-26 19:30:35 +00:00
}
// Reset the curly index back to -1 and reset ignores
2024-04-26 19:30:35 +00:00
startCurly = -1
2024-04-26 19:30:35 +00:00
startCurlyIgnore = []int{}
2024-04-26 19:30:35 +00:00
endCurly = -1
2024-04-26 19:30:35 +00:00
endCurlyIgnore = []int{}
2024-04-26 19:30:35 +00:00
i = -1 // Reset back to the start of the string
2024-04-26 19:30:35 +00:00
continue
2024-04-26 19:30:35 +00:00
}
// Couldnt find anything - mark curly brackets to skip and rerun
2024-04-26 19:30:35 +00:00
startCurlyIgnore = append(startCurlyIgnore, startCurly)
2024-04-26 19:30:35 +00:00
endCurlyIgnore = append(endCurlyIgnore, endCurly)
// Reset the curly index back to -1
2024-04-26 19:30:35 +00:00
startCurly = -1
2024-04-26 19:30:35 +00:00
endCurly = -1
2024-04-26 19:30:35 +00:00
i = -1 // Reset back to the start of the string
2024-04-26 19:30:35 +00:00
continue
2024-04-26 19:30:35 +00:00
}
return dataVal
2024-04-26 19:30:35 +00:00
}
// FixedWidthOptions defines values needed for csv generation
2024-04-26 19:30:35 +00:00
type FixedWidthOptions struct {
RowCount int `json:"row_count" xml:"row_count" fake:"{number:1,10}"`
Fields []Field `json:"fields" xml:"fields" fake:"{fields}"`
2024-04-26 19:30:35 +00:00
}
// FixedWidth generates an table of random data in fixed width format
2024-04-26 19:30:35 +00:00
// A nil FixedWidthOptions returns a randomly structured FixedWidth.
2024-04-26 19:30:35 +00:00
func FixedWidth(co *FixedWidthOptions) (string, error) { return fixeWidthFunc(globalFaker.Rand, co) }
// FixedWidth generates an table of random data in fixed width format
2024-04-26 19:30:35 +00:00
// A nil FixedWidthOptions returns a randomly structured FixedWidth.
2024-04-26 19:30:35 +00:00
func (f *Faker) FixedWidth(co *FixedWidthOptions) (string, error) { return fixeWidthFunc(f.Rand, co) }
// Function to generate a fixed width document
2024-04-26 19:30:35 +00:00
func fixeWidthFunc(r *rand.Rand, co *FixedWidthOptions) (string, error) {
2024-04-26 19:30:35 +00:00
// If we didn't get FixedWidthOptions, create a new random one
2024-04-26 19:30:35 +00:00
if co == nil {
2024-04-26 19:30:35 +00:00
co = &FixedWidthOptions{}
2024-04-26 19:30:35 +00:00
}
// Make sure you set a row count
2024-04-26 19:30:35 +00:00
if co.RowCount <= 0 {
2024-04-26 19:30:35 +00:00
co.RowCount = r.Intn(10) + 1
2024-04-26 19:30:35 +00:00
}
// Check fields
2024-04-26 19:30:35 +00:00
if len(co.Fields) <= 0 {
2024-04-26 19:30:35 +00:00
// Create random fields
2024-04-26 19:30:35 +00:00
co.Fields = []Field{
2024-04-26 19:30:35 +00:00
{Name: "Name", Function: "{firstname} {lastname}"},
2024-04-26 19:30:35 +00:00
{Name: "Email", Function: "email"},
2024-04-26 19:30:35 +00:00
{Name: "Password", Function: "password", Params: MapParams{"special": {"false"}, "space": {"false"}}},
}
2024-04-26 19:30:35 +00:00
}
data := [][]string{}
2024-04-26 19:30:35 +00:00
hasHeader := false
// Loop through fields, generate data and add to data array
2024-04-26 19:30:35 +00:00
for _, field := range co.Fields {
2024-04-26 19:30:35 +00:00
// Start new row
2024-04-26 19:30:35 +00:00
row := []string{}
// Add name to first value
2024-04-26 19:30:35 +00:00
if field.Name != "" {
2024-04-26 19:30:35 +00:00
hasHeader = true
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
row = append(row, field.Name)
// Get function
2024-04-26 19:30:35 +00:00
funcInfo := GetFuncLookup(field.Function)
2024-04-26 19:30:35 +00:00
var value any
2024-04-26 19:30:35 +00:00
if funcInfo == nil {
2024-04-26 19:30:35 +00:00
// Try to run the function through generate
2024-04-26 19:30:35 +00:00
for i := 0; i < co.RowCount; i++ {
2024-04-26 19:30:35 +00:00
row = append(row, generate(r, field.Function))
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
// Generate function value
2024-04-26 19:30:35 +00:00
var err error
2024-04-26 19:30:35 +00:00
for i := 0; i < co.RowCount; i++ {
2024-04-26 19:30:35 +00:00
value, err = funcInfo.Generate(r, &field.Params, funcInfo)
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
value = ""
2024-04-26 19:30:35 +00:00
}
// Add value to row
2024-04-26 19:30:35 +00:00
row = append(row, anyToString(value))
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
// Add row to data
2024-04-26 19:30:35 +00:00
data = append(data, row)
2024-04-26 19:30:35 +00:00
}
var result strings.Builder
// Calculate column widths
2024-04-26 19:30:35 +00:00
colWidths := make([]int, len(data))
2024-04-26 19:30:35 +00:00
for i, row := range data {
2024-04-26 19:30:35 +00:00
for _, value := range row {
2024-04-26 19:30:35 +00:00
width := len(value) + 5
2024-04-26 19:30:35 +00:00
if width > colWidths[i] {
2024-04-26 19:30:35 +00:00
colWidths[i] = width
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
// Append table rows to the string, excluding the entire row if the first value is empty
2024-04-26 19:30:35 +00:00
for i := 0; i < len(data[0]); i++ {
2024-04-26 19:30:35 +00:00
if !hasHeader && i == 0 {
2024-04-26 19:30:35 +00:00
continue // Skip the entire column if the first value is empty
2024-04-26 19:30:35 +00:00
}
var resultRow strings.Builder
2024-04-26 19:30:35 +00:00
for j, row := range data {
2024-04-26 19:30:35 +00:00
resultRow.WriteString(fmt.Sprintf("%-*s", colWidths[j], row[i]))
2024-04-26 19:30:35 +00:00
}
// Trim trailing spaces
2024-04-26 19:30:35 +00:00
result.WriteString(strings.TrimRight(resultRow.String(), " "))
// Only add new line if not the last row
2024-04-26 19:30:35 +00:00
if i != len(data[0])-1 {
2024-04-26 19:30:35 +00:00
result.WriteString("\n")
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
return result.String(), nil
2024-04-26 19:30:35 +00:00
}
// Regex will generate a string based upon a RE2 syntax
2024-04-26 19:30:35 +00:00
func Regex(regexStr string) string { return regex(globalFaker.Rand, regexStr) }
// Regex will generate a string based upon a RE2 syntax
2024-04-26 19:30:35 +00:00
func (f *Faker) Regex(regexStr string) string { return regex(f.Rand, regexStr) }
func regex(r *rand.Rand, regexStr string) (gen string) {
2024-04-26 19:30:35 +00:00
re, err := syntax.Parse(regexStr, syntax.Perl)
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return "Could not parse regex string"
2024-04-26 19:30:35 +00:00
}
// Panic catch
2024-04-26 19:30:35 +00:00
defer func() {
2024-04-26 19:30:35 +00:00
if r := recover(); r != nil {
2024-04-26 19:30:35 +00:00
gen = fmt.Sprint(r)
2024-04-26 19:30:35 +00:00
return
}
2024-04-26 19:30:35 +00:00
}()
return regexGenerate(r, re, len(regexStr)*100)
2024-04-26 19:30:35 +00:00
}
func regexGenerate(ra *rand.Rand, re *syntax.Regexp, limit int) string {
2024-04-26 19:30:35 +00:00
if limit <= 0 {
2024-04-26 19:30:35 +00:00
panic("Length limit reached when generating output")
2024-04-26 19:30:35 +00:00
}
op := re.Op
2024-04-26 19:30:35 +00:00
switch op {
2024-04-26 19:30:35 +00:00
case syntax.OpNoMatch: // matches no strings
2024-04-26 19:30:35 +00:00
// Do Nothing
2024-04-26 19:30:35 +00:00
case syntax.OpEmptyMatch: // matches empty string
2024-04-26 19:30:35 +00:00
return ""
2024-04-26 19:30:35 +00:00
case syntax.OpLiteral: // matches Runes sequence
2024-04-26 19:30:35 +00:00
var b strings.Builder
2024-04-26 19:30:35 +00:00
for _, ru := range re.Rune {
2024-04-26 19:30:35 +00:00
b.WriteRune(ru)
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
return b.String()
2024-04-26 19:30:35 +00:00
case syntax.OpCharClass: // matches Runes interpreted as range pair list
2024-04-26 19:30:35 +00:00
// number of possible chars
2024-04-26 19:30:35 +00:00
sum := 0
2024-04-26 19:30:35 +00:00
for i := 0; i < len(re.Rune); i += 2 {
2024-04-26 19:30:35 +00:00
sum += int(re.Rune[i+1]-re.Rune[i]) + 1
2024-04-26 19:30:35 +00:00
if re.Rune[i+1] == 0x10ffff { // rune range end
2024-04-26 19:30:35 +00:00
sum = -1
2024-04-26 19:30:35 +00:00
break
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
// pick random char in range (inverse match group)
2024-04-26 19:30:35 +00:00
if sum == -1 {
2024-04-26 19:30:35 +00:00
chars := []uint8{}
2024-04-26 19:30:35 +00:00
for j := 0; j < len(allStr); j++ {
2024-04-26 19:30:35 +00:00
c := allStr[j]
// Check c in range
2024-04-26 19:30:35 +00:00
for i := 0; i < len(re.Rune); i += 2 {
2024-04-26 19:30:35 +00:00
if rune(c) >= re.Rune[i] && rune(c) <= re.Rune[i+1] {
2024-04-26 19:30:35 +00:00
chars = append(chars, c)
2024-04-26 19:30:35 +00:00
break
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
if len(chars) > 0 {
2024-04-26 19:30:35 +00:00
return string([]byte{chars[ra.Intn(len(chars))]})
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
r := ra.Intn(int(sum))
2024-04-26 19:30:35 +00:00
var ru rune
2024-04-26 19:30:35 +00:00
sum = 0
2024-04-26 19:30:35 +00:00
for i := 0; i < len(re.Rune); i += 2 {
2024-04-26 19:30:35 +00:00
gap := int(re.Rune[i+1]-re.Rune[i]) + 1
2024-04-26 19:30:35 +00:00
if sum+gap > r {
2024-04-26 19:30:35 +00:00
ru = re.Rune[i] + rune(r-sum)
2024-04-26 19:30:35 +00:00
break
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
sum += gap
2024-04-26 19:30:35 +00:00
}
return string(ru)
2024-04-26 19:30:35 +00:00
case syntax.OpAnyCharNotNL, syntax.OpAnyChar: // matches any character(and except newline)
2024-04-26 19:30:35 +00:00
return randCharacter(ra, allStr)
2024-04-26 19:30:35 +00:00
case syntax.OpBeginLine: // matches empty string at beginning of line
2024-04-26 19:30:35 +00:00
case syntax.OpEndLine: // matches empty string at end of line
2024-04-26 19:30:35 +00:00
case syntax.OpBeginText: // matches empty string at beginning of text
2024-04-26 19:30:35 +00:00
case syntax.OpEndText: // matches empty string at end of text
2024-04-26 19:30:35 +00:00
case syntax.OpWordBoundary: // matches word boundary `\b`
2024-04-26 19:30:35 +00:00
case syntax.OpNoWordBoundary: // matches word non-boundary `\B`
2024-04-26 19:30:35 +00:00
case syntax.OpCapture: // capturing subexpression with index Cap, optional name Name
2024-04-26 19:30:35 +00:00
return regexGenerate(ra, re.Sub0[0], limit)
2024-04-26 19:30:35 +00:00
case syntax.OpStar: // matches Sub[0] zero or more times
2024-04-26 19:30:35 +00:00
var b strings.Builder
2024-04-26 19:30:35 +00:00
for i := 0; i < number(ra, 0, 10); i++ {
2024-04-26 19:30:35 +00:00
for _, rs := range re.Sub {
2024-04-26 19:30:35 +00:00
b.WriteString(regexGenerate(ra, rs, limit-b.Len()))
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 b.String()
2024-04-26 19:30:35 +00:00
case syntax.OpPlus: // matches Sub[0] one or more times
2024-04-26 19:30:35 +00:00
var b strings.Builder
2024-04-26 19:30:35 +00:00
for i := 0; i < number(ra, 1, 10); i++ {
2024-04-26 19:30:35 +00:00
for _, rs := range re.Sub {
2024-04-26 19:30:35 +00:00
b.WriteString(regexGenerate(ra, rs, limit-b.Len()))
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 b.String()
2024-04-26 19:30:35 +00:00
case syntax.OpQuest: // matches Sub[0] zero or one times
2024-04-26 19:30:35 +00:00
var b strings.Builder
2024-04-26 19:30:35 +00:00
for i := 0; i < number(ra, 0, 1); i++ {
2024-04-26 19:30:35 +00:00
for _, rs := range re.Sub {
2024-04-26 19:30:35 +00:00
b.WriteString(regexGenerate(ra, rs, limit-b.Len()))
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 b.String()
2024-04-26 19:30:35 +00:00
case syntax.OpRepeat: // matches Sub[0] at least Min times, at most Max (Max == -1 is no limit)
2024-04-26 19:30:35 +00:00
var b strings.Builder
2024-04-26 19:30:35 +00:00
count := 0
2024-04-26 19:30:35 +00:00
re.Max = int(math.Min(float64(re.Max), float64(10)))
2024-04-26 19:30:35 +00:00
if re.Max > re.Min {
2024-04-26 19:30:35 +00:00
count = ra.Intn(re.Max - re.Min + 1)
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
for i := 0; i < re.Min || i < (re.Min+count); i++ {
2024-04-26 19:30:35 +00:00
for _, rs := range re.Sub {
2024-04-26 19:30:35 +00:00
b.WriteString(regexGenerate(ra, rs, limit-b.Len()))
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 b.String()
2024-04-26 19:30:35 +00:00
case syntax.OpConcat: // matches concatenation of Subs
2024-04-26 19:30:35 +00:00
var b strings.Builder
2024-04-26 19:30:35 +00:00
for _, rs := range re.Sub {
2024-04-26 19:30:35 +00:00
b.WriteString(regexGenerate(ra, rs, limit-b.Len()))
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
return b.String()
2024-04-26 19:30:35 +00:00
case syntax.OpAlternate: // matches alternation of Subs
2024-04-26 19:30:35 +00:00
return regexGenerate(ra, re.Sub[number(ra, 0, len(re.Sub)-1)], limit)
2024-04-26 19:30:35 +00:00
}
return ""
2024-04-26 19:30:35 +00:00
}
// Map will generate a random set of map data
2024-04-26 19:30:35 +00:00
func Map() map[string]any { return mapFunc(globalFaker.Rand) }
// Map will generate a random set of map data
2024-04-26 19:30:35 +00:00
func (f *Faker) Map() map[string]any { return mapFunc(f.Rand) }
func mapFunc(r *rand.Rand) map[string]any {
2024-04-26 19:30:35 +00:00
m := map[string]any{}
randWordType := func() string {
2024-04-26 19:30:35 +00:00
s := randomString(r, []string{"lorem", "bs", "job", "name", "address"})
2024-04-26 19:30:35 +00:00
switch s {
2024-04-26 19:30:35 +00:00
case "bs":
2024-04-26 19:30:35 +00:00
return bs(r)
2024-04-26 19:30:35 +00:00
case "job":
2024-04-26 19:30:35 +00:00
return jobTitle(r)
2024-04-26 19:30:35 +00:00
case "name":
2024-04-26 19:30:35 +00:00
return name(r)
2024-04-26 19:30:35 +00:00
case "address":
2024-04-26 19:30:35 +00:00
return street(r) + ", " + city(r) + ", " + state(r) + " " + zip(r)
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
return word(r)
2024-04-26 19:30:35 +00:00
}
randSlice := func() []string {
2024-04-26 19:30:35 +00:00
var sl []string
2024-04-26 19:30:35 +00:00
for ii := 0; ii < number(r, 3, 10); ii++ {
2024-04-26 19:30:35 +00:00
sl = append(sl, word(r))
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
return sl
2024-04-26 19:30:35 +00:00
}
for i := 0; i < number(r, 3, 10); i++ {
2024-04-26 19:30:35 +00:00
t := randomString(r, []string{"string", "int", "float", "slice", "map"})
2024-04-26 19:30:35 +00:00
switch t {
2024-04-26 19:30:35 +00:00
case "string":
2024-04-26 19:30:35 +00:00
m[word(r)] = randWordType()
2024-04-26 19:30:35 +00:00
case "int":
2024-04-26 19:30:35 +00:00
m[word(r)] = number(r, 1, 10000000)
2024-04-26 19:30:35 +00:00
case "float":
2024-04-26 19:30:35 +00:00
m[word(r)] = float32Range(r, 1, 1000000)
2024-04-26 19:30:35 +00:00
case "slice":
2024-04-26 19:30:35 +00:00
m[word(r)] = randSlice()
2024-04-26 19:30:35 +00:00
case "map":
2024-04-26 19:30:35 +00:00
mm := map[string]any{}
2024-04-26 19:30:35 +00:00
tt := randomString(r, []string{"string", "int", "float", "slice"})
2024-04-26 19:30:35 +00:00
switch tt {
2024-04-26 19:30:35 +00:00
case "string":
2024-04-26 19:30:35 +00:00
mm[word(r)] = randWordType()
2024-04-26 19:30:35 +00:00
case "int":
2024-04-26 19:30:35 +00:00
mm[word(r)] = number(r, 1, 10000000)
2024-04-26 19:30:35 +00:00
case "float":
2024-04-26 19:30:35 +00:00
mm[word(r)] = float32Range(r, 1, 1000000)
2024-04-26 19:30:35 +00:00
case "slice":
2024-04-26 19:30:35 +00:00
mm[word(r)] = randSlice()
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
m[word(r)] = mm
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
return m
2024-04-26 19:30:35 +00:00
}
func addGenerateLookup() {
2024-04-26 19:30:35 +00:00
AddFuncLookup("generate", Info{
Display: "Generate",
Category: "generate",
2024-04-26 19:30:35 +00:00
Description: "Random string generated from string value based upon available data sets",
Example: "{firstname} {lastname} {email} - Markus Moen markusmoen@pagac.net",
Output: "string",
2024-04-26 19:30:35 +00:00
Params: []Param{
2024-04-26 19:30:35 +00:00
{Field: "str", Display: "String", Type: "string", Description: "String value to generate from"},
},
2024-04-26 19:30:35 +00:00
Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) {
2024-04-26 19:30:35 +00:00
str, err := info.GetString(m, "str")
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return nil, err
2024-04-26 19:30:35 +00:00
}
// Limit the length of the string passed
2024-04-26 19:30:35 +00:00
if len(str) > 1000 {
2024-04-26 19:30:35 +00:00
return nil, errors.New("string length is too large. limit to 1000 characters")
2024-04-26 19:30:35 +00:00
}
return generate(r, str), nil
2024-04-26 19:30:35 +00:00
},
})
AddFuncLookup("fixed_width", Info{
Display: "Fixed Width",
Category: "generate",
2024-04-26 19:30:35 +00:00
Description: "Fixed width rows of output data based on input fields",
2024-04-26 19:30:35 +00:00
Example: `Name Email Password Age
2024-04-26 19:30:35 +00:00
Markus Moen sylvanmraz@murphy.net 6VlvH6qqXc7g 13
2024-04-26 19:30:35 +00:00
Alayna Wuckert santinostanton@carroll.biz g7sLrS0gEwLO 46
2024-04-26 19:30:35 +00:00
Lura Lockman zacherykuhic@feil.name S8gV7Z64KlHG 12`,
Output: "[]byte",
2024-04-26 19:30:35 +00:00
ContentType: "text/plain",
2024-04-26 19:30:35 +00:00
Params: []Param{
2024-04-26 19:30:35 +00:00
{Field: "rowcount", Display: "Row Count", Type: "int", Default: "10", Description: "Number of rows"},
2024-04-26 19:30:35 +00:00
{Field: "fields", Display: "Fields", Type: "[]Field", Description: "Fields name, function and params"},
},
2024-04-26 19:30:35 +00:00
Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) {
2024-04-26 19:30:35 +00:00
co := FixedWidthOptions{}
rowCount, err := info.GetInt(m, "rowcount")
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return nil, err
2024-04-26 19:30:35 +00:00
}
co.RowCount = rowCount
fields, _ := info.GetStringArray(m, "fields")
// Check to make sure fields has length
2024-04-26 19:30:35 +00:00
if len(fields) > 0 {
2024-04-26 19:30:35 +00:00
co.Fields = make([]Field, len(fields))
2024-04-26 19:30:35 +00:00
for i, f := range fields {
2024-04-26 19:30:35 +00:00
// Unmarshal fields string into fields array
2024-04-26 19:30:35 +00:00
err = json.Unmarshal([]byte(f), &co.Fields[i])
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return nil, err
2024-04-26 19:30:35 +00:00
}
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
return nil, errors.New("missing fields")
2024-04-26 19:30:35 +00:00
}
out, err := fixeWidthFunc(r, &co)
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return nil, err
2024-04-26 19:30:35 +00:00
}
return out, nil
2024-04-26 19:30:35 +00:00
},
})
AddFuncLookup("regex", Info{
Display: "Regex",
Category: "generate",
2024-04-26 19:30:35 +00:00
Description: "Pattern-matching tool used in text processing to search and manipulate strings",
Example: "[abcdef]{5} - affec",
Output: "string",
2024-04-26 19:30:35 +00:00
Params: []Param{
2024-04-26 19:30:35 +00:00
{Field: "str", Display: "String", Type: "string", Description: "Regex RE2 syntax string"},
},
2024-04-26 19:30:35 +00:00
Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) {
2024-04-26 19:30:35 +00:00
str, err := info.GetString(m, "str")
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return nil, err
2024-04-26 19:30:35 +00:00
}
// Limit the length of the string passed
2024-04-26 19:30:35 +00:00
if len(str) > 500 {
2024-04-26 19:30:35 +00:00
return nil, errors.New("string length is too large. limit to 500 characters")
2024-04-26 19:30:35 +00:00
}
return regex(r, str), nil
2024-04-26 19:30:35 +00:00
},
})
AddFuncLookup("map", Info{
Display: "Map",
Category: "generate",
2024-04-26 19:30:35 +00:00
Description: "Data structure that stores key-value pairs",
2024-04-26 19:30:35 +00:00
Example: `{
2024-04-26 19:30:35 +00:00
"software": 7518355,
2024-04-26 19:30:35 +00:00
"that": ["despite", "pack", "whereas", "recently", "there", "anyone", "time", "read"],
2024-04-26 19:30:35 +00:00
"use": 683598,
2024-04-26 19:30:35 +00:00
"whom": "innovate",
2024-04-26 19:30:35 +00:00
"yourselves": 1987784
2024-04-26 19:30:35 +00:00
}`,
Output: "map[string]any",
2024-04-26 19:30:35 +00:00
ContentType: "application/json",
2024-04-26 19:30:35 +00:00
Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) {
2024-04-26 19:30:35 +00:00
return mapFunc(r), nil
2024-04-26 19:30:35 +00:00
},
})
2024-04-26 19:30:35 +00:00
}