summaryrefslogtreecommitdiff
path: root/vendor/github.com/go-faker/faker/v4/faker.go
diff options
context:
space:
mode:
authorMitja Felicijan <mitja.felicijan@gmail.com>2026-02-05 00:37:32 +0100
committerMitja Felicijan <mitja.felicijan@gmail.com>2026-02-05 00:37:32 +0100
commit6960aecc25400320adee1b8802a86839326e15b6 (patch)
tree334f7ca9491080a5e6f9a9747da77281c4958ba2 /vendor/github.com/go-faker/faker/v4/faker.go
downloadhepi-6960aecc25400320adee1b8802a86839326e15b6.tar.gz
Engage!
Diffstat (limited to 'vendor/github.com/go-faker/faker/v4/faker.go')
-rw-r--r--vendor/github.com/go-faker/faker/v4/faker.go1412
1 files changed, 1412 insertions, 0 deletions
diff --git a/vendor/github.com/go-faker/faker/v4/faker.go b/vendor/github.com/go-faker/faker/v4/faker.go
new file mode 100644
index 0000000..a4f66f4
--- /dev/null
+++ b/vendor/github.com/go-faker/faker/v4/faker.go
@@ -0,0 +1,1412 @@
+package faker
+
+// Faker is a simple fake data generator for your own struct.
+// Save your time, and Fake your data for your testing now.
+import (
+ cryptorand "crypto/rand"
+ "errors"
+ "fmt"
+ mathrand "math/rand"
+ "reflect"
+ "regexp"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ fakerErrors "github.com/go-faker/faker/v4/pkg/errors"
+ "github.com/go-faker/faker/v4/pkg/interfaces"
+ "github.com/go-faker/faker/v4/pkg/options"
+ "github.com/go-faker/faker/v4/pkg/slice"
+)
+
+var (
+ // Unique values are kept in memory so the generator retries if the value already exists
+ uniqueValues = &sync.Map{}
+)
+
+// Supported tags
+const (
+ letterIdxBits = 6 // 6 bits to represent a letter index
+ letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
+ letterIdxMax = 63 / letterIdxBits // # of letter indices fitting in 63 bits
+ maxRetry = 10000 // max number of retry for unique values
+ keep = "keep"
+ unique = "unique"
+ ID = "uuid_digit"
+ HyphenatedID = "uuid_hyphenated"
+ EmailTag = "email"
+ MacAddressTag = "mac_address"
+ DomainNameTag = "domain_name"
+ UserNameTag = "username"
+ URLTag = "url"
+ IPV4Tag = "ipv4"
+ IPV6Tag = "ipv6"
+ PASSWORD = "password"
+ JWT = "jwt"
+ LATITUDE = "lat"
+ LONGITUDE = "long"
+ RealAddressTag = "real_address"
+ CreditCardNumber = "cc_number"
+ CreditCardType = "cc_type"
+ PhoneNumber = "phone_number"
+ TollFreeNumber = "toll_free_number"
+ E164PhoneNumberTag = "e_164_phone_number"
+ TitleMaleTag = "title_male"
+ TitleFemaleTag = "title_female"
+ FirstNameTag = "first_name"
+ FirstNameMaleTag = "first_name_male"
+ FirstNameFemaleTag = "first_name_female"
+ LastNameTag = "last_name"
+ NAME = "name"
+ ChineseFirstNameTag = "chinese_first_name"
+ ChineseLastNameTag = "chinese_last_name"
+ ChineseNameTag = "chinese_name"
+ GENDER = "gender"
+ UnixTimeTag = "unix_time"
+ DATE = "date"
+ TIME = "time"
+ MonthNameTag = "month_name"
+ YEAR = "year"
+ DayOfWeekTag = "day_of_week"
+ DayOfMonthTag = "day_of_month"
+ TIMESTAMP = "timestamp"
+ CENTURY = "century"
+ TIMEZONE = "timezone"
+ TimePeriodTag = "time_period"
+ WORD = "word"
+ SENTENCE = "sentence"
+ PARAGRAPH = "paragraph"
+ CurrencyTag = "currency"
+ AmountTag = "amount"
+ AmountWithCurrencyTag = "amount_with_currency"
+ SKIP = "-"
+ Length = "len"
+ SliceLength = "slice_len"
+ Language = "lang"
+ BoundaryStart = "boundary_start"
+ BoundaryEnd = "boundary_end"
+ Equals = "="
+ comma = ","
+ colon = ":"
+ ONEOF = "oneof"
+ RussianFirstNameMaleTag = "russian_first_name_male"
+ RussianLastNameMaleTag = "russian_last_name_male"
+ RussianFirstNameFemaleTag = "russian_first_name_female"
+ RussianLastNameFemaleTag = "russian_last_name_female"
+ BloodTypeTag = "blood_type"
+ CountryInfoTag = "country_info"
+ UserAgentTag = "user_agent"
+)
+
+// PriorityTags define the priority order of the tag
+var PriorityTags = []string{ID, HyphenatedID, EmailTag, MacAddressTag, DomainNameTag, UserNameTag, URLTag, IPV4Tag,
+ IPV6Tag, PASSWORD, JWT, CountryInfoTag, LATITUDE, LONGITUDE, CreditCardNumber, CreditCardType, PhoneNumber, TollFreeNumber,
+ E164PhoneNumberTag, TitleMaleTag, TitleFemaleTag, FirstNameTag, FirstNameMaleTag, FirstNameFemaleTag, LastNameTag,
+ NAME, ChineseFirstNameTag, ChineseLastNameTag, ChineseNameTag, GENDER, UnixTimeTag, DATE, TIME, MonthNameTag,
+ YEAR, DayOfWeekTag, DayOfMonthTag, TIMESTAMP, CENTURY, TIMEZONE, TimePeriodTag, WORD, SENTENCE, PARAGRAPH,
+ CurrencyTag, AmountTag, AmountWithCurrencyTag, SKIP, Length, SliceLength, Language, BoundaryStart, BoundaryEnd, ONEOF, BloodTypeTag,
+ UserAgentTag,
+}
+
+type mapperTagCustom struct {
+ sync.Map
+}
+
+func (m *mapperTagCustom) Load(key string) (interfaces.TaggedFunction, bool) {
+ mappedTagFunc, ok := m.Map.Load(key)
+ if !ok {
+ return nil, ok
+ }
+ tagFunc, ok := mappedTagFunc.(interfaces.TaggedFunction)
+ if ok {
+ return tagFunc, ok
+ }
+ tagPureFunc, ok := mappedTagFunc.(func(v reflect.Value) (interface{}, error))
+ if ok {
+ return tagPureFunc, ok
+ }
+ return nil, false
+}
+
+func (m *mapperTagCustom) Store(key string, taggedFunc interfaces.TaggedFunction) {
+ m.Map.Store(key, taggedFunc)
+}
+
+var defaultTag = sync.Map{}
+
+func initDefaultTag() {
+ defaultTag.Store(BloodTypeTag, BloodTypeTag)
+ defaultTag.Store(EmailTag, EmailTag)
+ defaultTag.Store(MacAddressTag, MacAddressTag)
+ defaultTag.Store(DomainNameTag, DomainNameTag)
+ defaultTag.Store(URLTag, URLTag)
+ defaultTag.Store(UserNameTag, UserNameTag)
+ defaultTag.Store(IPV4Tag, IPV4Tag)
+ defaultTag.Store(IPV6Tag, IPV6Tag)
+ defaultTag.Store(PASSWORD, PASSWORD)
+ defaultTag.Store(JWT, JWT)
+ defaultTag.Store(CreditCardType, CreditCardType)
+ defaultTag.Store(CreditCardNumber, CreditCardNumber)
+ defaultTag.Store(CountryInfoTag, CountryInfoTag)
+ defaultTag.Store(LATITUDE, LATITUDE)
+ defaultTag.Store(LONGITUDE, LONGITUDE)
+ defaultTag.Store(RealAddressTag, RealAddressTag)
+ defaultTag.Store(PhoneNumber, PhoneNumber)
+ defaultTag.Store(TollFreeNumber, TollFreeNumber)
+ defaultTag.Store(E164PhoneNumberTag, E164PhoneNumberTag)
+ defaultTag.Store(TitleMaleTag, TitleMaleTag)
+ defaultTag.Store(TitleFemaleTag, TitleFemaleTag)
+ defaultTag.Store(FirstNameTag, FirstNameTag)
+ defaultTag.Store(FirstNameMaleTag, FirstNameMaleTag)
+ defaultTag.Store(FirstNameFemaleTag, FirstNameFemaleTag)
+ defaultTag.Store(LastNameTag, LastNameTag)
+ defaultTag.Store(NAME, NAME)
+ defaultTag.Store(ChineseFirstNameTag, ChineseFirstNameTag)
+ defaultTag.Store(ChineseLastNameTag, ChineseLastNameTag)
+ defaultTag.Store(ChineseNameTag, ChineseNameTag)
+ defaultTag.Store(GENDER, GENDER)
+ defaultTag.Store(UnixTimeTag, UnixTimeTag)
+ defaultTag.Store(DATE, DATE)
+ defaultTag.Store(TIME, TimeFormat)
+ defaultTag.Store(MonthNameTag, MonthNameTag)
+ defaultTag.Store(YEAR, YearFormat)
+ defaultTag.Store(DayOfWeekTag, DayOfWeekTag)
+ defaultTag.Store(DayOfMonthTag, DayOfMonthFormat)
+ defaultTag.Store(TIMESTAMP, TIMESTAMP)
+ defaultTag.Store(CENTURY, CENTURY)
+ defaultTag.Store(TIMEZONE, TIMEZONE)
+ defaultTag.Store(TimePeriodTag, TimePeriodFormat)
+ defaultTag.Store(WORD, WORD)
+ defaultTag.Store(SENTENCE, SENTENCE)
+ defaultTag.Store(PARAGRAPH, PARAGRAPH)
+ defaultTag.Store(CurrencyTag, CurrencyTag)
+ defaultTag.Store(AmountTag, AmountTag)
+ defaultTag.Store(AmountWithCurrencyTag, AmountWithCurrencyTag)
+ defaultTag.Store(ID, ID)
+ defaultTag.Store(HyphenatedID, HyphenatedID)
+ defaultTag.Store(RussianFirstNameMaleTag, RussianFirstNameMaleTag)
+ defaultTag.Store(RussianLastNameMaleTag, RussianLastNameMaleTag)
+ defaultTag.Store(RussianFirstNameFemaleTag, RussianFirstNameFemaleTag)
+ defaultTag.Store(RussianLastNameFemaleTag, RussianLastNameFemaleTag)
+ defaultTag.Store(UserAgentTag, UserAgentTag)
+}
+
+var mapperTag = mapperTagCustom{}
+
+func initMapperTagDefault() {
+ mapperTag.Store(CreditCardType, GetPayment().CreditCardType)
+ mapperTag.Store(CreditCardNumber, GetPayment().CreditCardNumber)
+ mapperTag.Store(CountryInfoTag, GetAddress().CountryInfo)
+ mapperTag.Store(LATITUDE, GetAddress().Latitude)
+ mapperTag.Store(LONGITUDE, GetAddress().Longitude)
+ mapperTag.Store(RealAddressTag, GetAddress().RealWorld)
+ mapperTag.Store(PhoneNumber, GetPhoner().PhoneNumber)
+ mapperTag.Store(TollFreeNumber, GetPhoner().TollFreePhoneNumber)
+ mapperTag.Store(E164PhoneNumberTag, GetPhoner().E164PhoneNumber)
+ mapperTag.Store(TitleMaleTag, GetPerson().TitleMale)
+ mapperTag.Store(TitleFemaleTag, GetPerson().TitleFeMale)
+ mapperTag.Store(FirstNameTag, GetPerson().FirstName)
+ mapperTag.Store(FirstNameMaleTag, GetPerson().FirstNameMale)
+ mapperTag.Store(FirstNameFemaleTag, GetPerson().FirstNameFemale)
+ mapperTag.Store(LastNameTag, GetPerson().LastName)
+ mapperTag.Store(NAME, GetPerson().Name)
+ mapperTag.Store(ChineseFirstNameTag, GetPerson().ChineseFirstName)
+ mapperTag.Store(ChineseLastNameTag, GetPerson().ChineseLastName)
+ mapperTag.Store(ChineseNameTag, GetPerson().ChineseName)
+ mapperTag.Store(GENDER, GetPerson().Gender)
+ mapperTag.Store(UnixTimeTag, GetDateTimer().UnixTime)
+ mapperTag.Store(DATE, GetDateTimer().Date)
+ mapperTag.Store(TIME, GetDateTimer().Time)
+ mapperTag.Store(MonthNameTag, GetDateTimer().MonthName)
+ mapperTag.Store(YEAR, GetDateTimer().Year)
+ mapperTag.Store(DayOfWeekTag, GetDateTimer().DayOfWeek)
+ mapperTag.Store(DayOfMonthTag, GetDateTimer().DayOfMonth)
+ mapperTag.Store(TIMESTAMP, GetDateTimer().Timestamp)
+ mapperTag.Store(CENTURY, GetDateTimer().Century)
+ mapperTag.Store(TIMEZONE, GetDateTimer().TimeZone)
+ mapperTag.Store(TimePeriodTag, GetDateTimer().TimePeriod)
+ mapperTag.Store(WORD, GetLorem().Word)
+ mapperTag.Store(SENTENCE, GetLorem().Sentence)
+ mapperTag.Store(PARAGRAPH, GetLorem().Paragraph)
+ mapperTag.Store(CurrencyTag, GetPrice().Currency)
+ mapperTag.Store(AmountTag, GetPrice().Amount)
+ mapperTag.Store(AmountWithCurrencyTag, GetPrice().AmountWithCurrency)
+ mapperTag.Store(ID, GetIdentifier().Digit)
+ mapperTag.Store(HyphenatedID, GetIdentifier().Hyphenated)
+ mapperTag.Store(RussianFirstNameMaleTag, GetPerson().RussianFirstNameMale)
+ mapperTag.Store(RussianFirstNameFemaleTag, GetPerson().RussianFirstNameFemale)
+ mapperTag.Store(RussianLastNameMaleTag, GetPerson().RussianLastNameMale)
+ mapperTag.Store(RussianLastNameFemaleTag, GetPerson().RussianLastNameFemale)
+ mapperTag.Store(BloodTypeTag, GetBlood().BloodGroup)
+ mapperTag.Store(UserAgentTag, GetUserAgent().UserAgent)
+}
+
+// Compiled regexp
+var (
+ findLangReg *regexp.Regexp
+ findLenReg *regexp.Regexp
+ findSliceLenReg *regexp.Regexp
+)
+
+func init() {
+ rand = mathrand.New(NewSafeSource(mathrand.NewSource(time.Now().UnixNano())))
+ crypto = cryptorand.Reader
+}
+
+func init() {
+ findLangReg, _ = regexp.Compile("lang=[a-z]{3}")
+ findLenReg, _ = regexp.Compile(`len=\d+`)
+ findSliceLenReg, _ = regexp.Compile(`slice_len=\d+`)
+
+ randNameFlag = rand.Intn(100) // for person
+}
+
+func init() {
+ initDefaultTag()
+ initMapperTagDefault()
+}
+
+// ResetUnique is used to forget generated unique values.
+// Call this when you're done generating a dataset.
+func ResetUnique() {
+ uniqueValues = &sync.Map{}
+}
+
+var (
+ SetGenerateUniqueValues = options.SetGenerateUniqueValues
+ SetIgnoreInterface = options.SetIgnoreInterface
+ SetRandomStringLength = options.SetRandomStringLength
+ SetStringLang = options.SetStringLang
+ SetRandomMapAndSliceSize = options.SetRandomMapAndSliceSize
+ SetRandomMapAndSliceMaxSize = options.SetRandomMapAndSliceMaxSize
+ SetRandomMapAndSliceMinSize = options.SetRandomMapAndSliceMinSize
+ SetRandomNumberBoundaries = options.SetRandomNumberBoundaries
+)
+
+func initMapperTagWithOption(opts ...options.OptionFunc) {
+ mapperTag.Store(EmailTag, GetNetworker(opts...).Email)
+ mapperTag.Store(MacAddressTag, GetNetworker(opts...).MacAddress)
+ mapperTag.Store(DomainNameTag, GetNetworker(opts...).DomainName)
+ mapperTag.Store(URLTag, GetNetworker(opts...).URL)
+ mapperTag.Store(UserNameTag, GetNetworker(opts...).UserName)
+ mapperTag.Store(IPV4Tag, GetNetworker(opts...).IPv4)
+ mapperTag.Store(IPV6Tag, GetNetworker(opts...).IPv6)
+ mapperTag.Store(PASSWORD, GetNetworker(opts...).Password)
+ mapperTag.Store(JWT, GetNetworker(opts...).Jwt)
+}
+
+func initOption(opt ...options.OptionFunc) *options.Options {
+ opts := options.BuildOptions(opt)
+ initMapperTagWithOption(opt...)
+ return opts
+}
+
+// FakeData is the main function. Will generate a fake data based on your struct. You can use this for automation testing, or anything that need automated data.
+// You don't need to Create your own data for your testing.
+func FakeData(a interface{}, opt ...options.OptionFunc) error {
+ opts := initOption(opt...)
+ reflectType := reflect.TypeOf(a)
+
+ if reflectType.Kind() != reflect.Ptr {
+ return errors.New(fakerErrors.ErrValueNotPtr)
+ }
+
+ if reflect.ValueOf(a).IsNil() {
+ return fmt.Errorf(fakerErrors.ErrNotSupportedPointer, reflectType.Elem().String())
+ }
+
+ rval := reflect.ValueOf(a)
+ finalValue, err := getFakedValue(a, opts)
+ if err != nil {
+ return err
+ }
+
+ if rval.Elem().CanSet() && rval.Elem().
+ CanConvert(reflectType.Elem()) {
+ rval.Elem().Set(finalValue.Elem().
+ Convert(reflectType.Elem()))
+ }
+ return nil
+}
+
+// AddProvider extend faker with tag to generate fake data with specified custom algorithm
+// Example:
+//
+// type Gondoruwo struct {
+// Name string
+// Locatadata int
+// }
+//
+// type Sample struct {
+// ID int64 `faker:"customIdFaker"`
+// Gondoruwo Gondoruwo `faker:"gondoruwo"`
+// Danger string `faker:"danger"`
+// }
+//
+// func CustomGenerator() {
+// // explicit
+// faker.AddProvider("customIdFaker", func(v reflect.Value) (interface{}, error) {
+// return int64(43), nil
+// })
+// // functional
+// faker.AddProvider("danger", func() faker.TaggedFunction {
+// return func(v reflect.Value) (interface{}, error) {
+// return "danger-ranger", nil
+// }
+// }())
+// faker.AddProvider("gondoruwo", func(v reflect.Value) (interface{}, error) {
+// obj := Gondoruwo{
+// Name: "Power",
+// Locatadata: 324,
+// }
+// return obj, nil
+// })
+// }
+//
+// func main() {
+// CustomGenerator()
+// var sample Sample
+// faker.FakeData(&sample)
+// fmt.Printf("%+v", sample)
+// }
+//
+// Will print
+//
+// {ID:43 Gondoruwo:{Name:Power Locatadata:324} Danger:danger-ranger}
+//
+// Notes: when using a custom provider make sure to return the same type as the field
+func AddProvider(tag string, provider interfaces.TaggedFunction) error {
+ if _, ok := mapperTag.Load(tag); ok {
+ return errors.New(fakerErrors.ErrTagAlreadyExists)
+ }
+ PriorityTags = append(PriorityTags, tag)
+ mapperTag.Store(tag, provider)
+
+ return nil
+}
+
+// RemoveProvider removes existing customization added with AddProvider
+func RemoveProvider(tag string) error {
+ if _, ok := mapperTag.Load(tag); !ok {
+ return errors.New(fakerErrors.ErrTagDoesNotExist)
+ }
+ mapperTag.Delete(tag)
+ return nil
+}
+
+func getFakedValue(item interface{}, opts *options.Options) (reflect.Value, error) {
+ t := reflect.TypeOf(item)
+ if t == nil {
+ if opts.IgnoreInterface {
+ return reflect.ValueOf(nil), nil
+ }
+ return reflect.Value{}, fmt.Errorf("interface{} not allowed")
+ }
+ if opts.MaxDepthOption.RecursionOutOfLimit(t) {
+ return reflect.Zero(t), nil
+ }
+ opts.MaxDepthOption.RememberType(t)
+ defer func() {
+ opts.MaxDepthOption.ForgetType(t)
+ }()
+ k := t.Kind()
+ switch k {
+ case reflect.Ptr:
+ v := reflect.New(t.Elem())
+ var val reflect.Value
+ var err error
+ if item != reflect.Zero(reflect.TypeOf(item)).Interface() {
+ val, err = getFakedValue(reflect.ValueOf(item).Elem().Interface(), opts)
+
+ } else {
+ val, err = getFakedValue(v.Elem().Interface(), opts)
+ }
+ if err != nil {
+ return reflect.Value{}, err
+ }
+
+ if reflect.ValueOf(val).IsZero() {
+ return v, nil
+ }
+
+ if v.Elem().CanSet() && v.Elem().CanConvert(t.Elem()) {
+ v.Elem().Set(val.Convert(t.Elem()))
+ }
+ return v, nil
+ case reflect.Struct:
+ if structTypeProvider, f := opts.StructTypeProviders[t]; f {
+ ft, err := structTypeProvider()
+ return reflect.ValueOf(ft), err
+ }
+ originalDataVal := reflect.ValueOf(item)
+ v := reflect.New(t).Elem()
+ if opts.MaxFieldDepthOption == 0 {
+ return v, nil
+ } else if opts.MaxFieldDepthOption > 0 {
+ opts.MaxFieldDepthOption--
+ defer func() { opts.MaxFieldDepthOption++ }()
+ }
+ retry := 0 // error if cannot generate unique value after maxRetry tries
+ for i := 0; i < v.NumField(); i++ {
+ if !v.Field(i).CanSet() {
+ continue // to avoid panic to set on unexported field in struct
+ }
+
+ if _, ok := opts.IgnoreFields[t.Field(i).Name]; ok {
+ continue
+ }
+
+ if p, ok := opts.FieldProviders[t.Field(i).Name]; ok {
+ val, err := p()
+ if err != nil {
+ return reflect.Value{}, fmt.Errorf("custom provider for field %s: %w", t.Field(i).Name, err)
+ }
+ v.Field(i).Set(reflect.ValueOf(val))
+ continue
+ }
+
+ tags := decodeTags(t, i, opts.TagName)
+ switch {
+ case tags.keepOriginal:
+ zero, err := isZero(reflect.ValueOf(item).Field(i))
+ if err != nil {
+ return reflect.Value{}, err
+ }
+ if zero {
+ err := setDataWithTag(v.Field(i).Addr(), tags.fieldType, *opts)
+ if err != nil {
+ return reflect.Value{}, err
+ }
+ continue
+ }
+ v.Field(i).Set(reflect.ValueOf(item).Field(i))
+ case tags.fieldType == "":
+ val, err := getFakedValue(v.Field(i).Interface(), opts)
+ if err != nil {
+ return reflect.Value{}, err
+ }
+
+ if v.Field(i).CanSet() {
+ if !reflect.ValueOf(val).IsZero() && val.CanConvert(v.Field(i).Type()) {
+ val = val.Convert(v.Field(i).Type())
+ v.Field(i).Set(val)
+ }
+
+ }
+ case tags.fieldType == SKIP:
+ data := originalDataVal.Field(i).Interface()
+ if v.CanSet() && data != nil {
+ v.Field(i).Set(reflect.ValueOf(data))
+ }
+ default:
+ err := setDataWithTag(v.Field(i).Addr(), tags.fieldType, *opts)
+ if err != nil {
+ return reflect.Value{}, err
+ }
+ }
+
+ if tags.unique {
+ if retry >= maxRetry {
+ return reflect.Value{}, fmt.Errorf(fakerErrors.ErrUniqueFailure, reflect.TypeOf(item).Field(i).Name)
+ }
+ value := v.Field(i).Interface()
+ uniqueVal, _ := uniqueValues.Load(tags.fieldType)
+ uniqueValArr, _ := uniqueVal.([]interface{})
+ if slice.ContainsValue(uniqueValArr, value) { // Retry if unique value already found
+ i--
+ retry++
+ continue
+ }
+ retry = 0
+ uniqueValues.Store(tags.fieldType, append(uniqueValArr, value))
+ } else {
+ retry = 0
+ }
+
+ }
+ return v, nil
+
+ case reflect.String:
+ res, err := randomString(opts.RandomStringLength, *opts)
+ return reflect.ValueOf(res), err
+ case reflect.Slice:
+
+ length := randomSliceAndMapSize(*opts)
+ if opts.SetSliceMapNilIfLenZero && length == 0 {
+ return reflect.Zero(t), nil
+ }
+ v := reflect.MakeSlice(t, length, length)
+ for i := 0; i < length; i++ {
+ val, err := getFakedValue(v.Index(i).Interface(), opts)
+ if err != nil {
+ return reflect.Value{}, err
+ }
+ // if the value generated is NIL/Zero
+ // it will kept it as nil
+ if reflect.ValueOf(val).IsZero() {
+ continue
+ }
+ if val.CanConvert(v.Index(i).Type()) {
+ val = val.Convert(v.Index(i).Type())
+ v.Index(i).Set(val)
+ }
+ }
+ return v, nil
+ case reflect.Array:
+ v := reflect.New(t).Elem()
+ for i := 0; i < v.Len(); i++ {
+ val, err := getFakedValue(v.Index(i).Interface(), opts)
+ if err != nil {
+ return reflect.Value{}, err
+ }
+ if reflect.ValueOf(val).IsZero() {
+ continue
+ }
+ if val.CanConvert(v.Index(i).Type()) {
+ val = val.Convert(v.Index(i).Type())
+ }
+ v.Index(i).Set(val)
+ }
+ return v, nil
+ case reflect.Int:
+ return reflect.ValueOf(randomInteger(opts)), nil
+ case reflect.Int8:
+ return reflect.ValueOf(int8(randomInteger(opts))), nil
+ case reflect.Int16:
+ return reflect.ValueOf(int16(randomInteger(opts))), nil
+ case reflect.Int32:
+ return reflect.ValueOf(int32(randomInteger(opts))), nil
+ case reflect.Int64:
+ return reflect.ValueOf(int64(randomInteger(opts))), nil
+ case reflect.Float32:
+ return reflect.ValueOf(float32(randomFloat(opts))), nil
+ case reflect.Float64:
+ return reflect.ValueOf(randomFloat(opts)), nil
+ case reflect.Bool:
+ val := rand.Intn(2) > 0
+ return reflect.ValueOf(val), nil
+
+ case reflect.Uint:
+ return reflect.ValueOf(uint(randomInteger(opts))), nil
+
+ case reflect.Uint8:
+ return reflect.ValueOf(uint8(randomInteger(opts))), nil
+
+ case reflect.Uint16:
+ return reflect.ValueOf(uint16(randomInteger(opts))), nil
+
+ case reflect.Uint32:
+ return reflect.ValueOf(uint32(randomInteger(opts))), nil
+
+ case reflect.Uint64:
+ return reflect.ValueOf(uint64(randomInteger(opts))), nil
+
+ case reflect.Map:
+ length := randomSliceAndMapSize(*opts)
+ if opts.SetSliceMapNilIfLenZero && length == 0 {
+ return reflect.Zero(t), nil
+ }
+ v := reflect.MakeMap(t)
+ for i := 0; i < length; i++ {
+ keyInstance := reflect.New(t.Key()).Elem().Interface()
+ key, err := getFakedValue(keyInstance, opts)
+ if err != nil {
+ return reflect.Value{}, err
+ }
+
+ valueInstance := reflect.New(t.Elem()).Elem().Interface()
+ val, err := getFakedValue(valueInstance, opts)
+ if err != nil {
+ return reflect.Value{}, err
+ }
+
+ keyIsZero := reflect.ValueOf(key).IsZero()
+ valIsZero := reflect.ValueOf(val).IsZero()
+
+ if keyIsZero || valIsZero {
+ continue
+ }
+ key = key.Convert(t.Key())
+ val = val.Convert(v.Type().Elem())
+ v.SetMapIndex(key, val)
+ }
+ return v, nil
+ default:
+ err := fmt.Errorf("no support for kind %+v", t)
+ return reflect.Value{}, err
+ }
+
+}
+
+func isZero(field reflect.Value) (bool, error) {
+ if field.Kind() == reflect.Map {
+ return field.Len() == 0, nil
+ }
+
+ for _, kind := range []reflect.Kind{reflect.Struct, reflect.Slice, reflect.Array} {
+ if kind == field.Kind() {
+ return false, fmt.Errorf("keep not allowed on struct")
+ }
+ }
+ return reflect.Zero(field.Type()).Interface() == field.Interface(), nil
+}
+
+func decodeTags(typ reflect.Type, i int, tagName string) structTag {
+ tagField := typ.Field(i).Tag.Get(tagName)
+ tags := strings.Split(tagField, ",")
+
+ keepOriginal := false
+ uni := false
+ res := make([]string, 0)
+ pMap := make(map[string]string)
+ for _, tag := range tags {
+ if tag == keep {
+ keepOriginal = true
+ continue
+ } else if tag == unique {
+ uni = true
+ continue
+ }
+ // res = append(res, tag)
+ ptag := strings.ToLower(strings.Trim(strings.Split(tag, "=")[0], " "))
+ pMap[ptag] = tag
+ ptag = strings.ToLower(strings.Trim(strings.Split(tag, ":")[0], " "))
+ pMap[ptag] = tag
+ }
+ // Priority
+ for _, ptag := range PriorityTags {
+ if tag, ok := pMap[ptag]; ok {
+ if ptag == ONEOF {
+ res = append(res, tags...)
+ } else {
+ res = append(res, tag)
+ }
+ delete(pMap, ptag)
+ }
+ }
+ // custom,keep,unique
+ if len(res) < 1 {
+ if !keepOriginal && !uni {
+ res = append(res, tags...)
+ }
+ }
+
+ return structTag{
+ fieldType: strings.Join(res, ","),
+ unique: uni,
+ keepOriginal: keepOriginal,
+ }
+}
+
+type structTag struct {
+ fieldType string
+ unique bool
+ keepOriginal bool
+}
+
+func setDataWithTag(v reflect.Value, tag string, opt options.Options) error {
+ if v.Kind() != reflect.Ptr {
+ return errors.New(fakerErrors.ErrValueNotPtr)
+ }
+ v = reflect.Indirect(v)
+ switch v.Kind() {
+ case reflect.Ptr:
+ if _, exist := mapperTag.Load(tag); !exist {
+ newv := reflect.New(v.Type().Elem())
+ if err := setDataWithTag(newv, tag, opt); err != nil {
+ return err
+ }
+ v.Set(newv)
+ return nil
+ }
+ if _, def := defaultTag.Load(tag); !def {
+ tagFunc, ok := mapperTag.Load(tag)
+ if !ok {
+ return fmt.Errorf(fakerErrors.ErrTagNotSupported, tag)
+ }
+ res, err := tagFunc(v)
+ if err != nil {
+ return err
+ }
+ v.Set(reflect.ValueOf(res))
+ return nil
+ }
+
+ t := v.Type()
+ newv := reflect.New(t.Elem())
+ tagFunc, ok := mapperTag.Load(tag)
+ if !ok {
+ return fmt.Errorf(fakerErrors.ErrTagNotSupported, tag)
+ }
+ res, err := tagFunc(newv.Elem())
+ if err != nil {
+ return err
+ }
+ rval := reflect.ValueOf(res)
+ newv.Elem().Set(rval)
+ v.Set(newv)
+ return nil
+ case reflect.String:
+ return userDefinedString(v, tag, opt)
+ case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int8, reflect.Int16, reflect.Uint, reflect.Uint8,
+ reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64:
+ return userDefinedNumber(v, tag)
+ case reflect.Slice, reflect.Array:
+ return userDefinedArray(v, tag, opt)
+ case reflect.Map:
+ return userDefinedMap(v, tag, opt)
+ default:
+ tagFunc, ok := mapperTag.Load(tag)
+ if !ok {
+ return fmt.Errorf(fakerErrors.ErrTagNotSupported, tag)
+ }
+ res, err := tagFunc(v)
+ if err != nil {
+ return err
+ }
+ v.Set(reflect.ValueOf(res))
+ }
+ return nil
+}
+
+func userDefinedMap(v reflect.Value, tag string, opt options.Options) error {
+ if tagFunc, ok := mapperTag.Load(tag); ok {
+ res, err := tagFunc(v)
+ if err != nil {
+ return err
+ }
+
+ v.Set(reflect.ValueOf(res))
+ return nil
+ }
+
+ length := randomSliceAndMapSize(opt)
+ if opt.SetSliceMapNilIfLenZero && length == 0 {
+ v.Set(reflect.Zero(v.Type()))
+ return nil
+ }
+ definedMap := reflect.MakeMap(v.Type())
+ for i := 0; i < length; i++ {
+ key, err := getValueWithTag(v.Type().Key(), tag, opt)
+ if err != nil {
+ return err
+ }
+ val, err := getValueWithTag(v.Type().Elem(), tag, opt)
+ if err != nil {
+ return err
+ }
+ definedMap.SetMapIndex(reflect.ValueOf(key), reflect.ValueOf(val))
+ }
+ v.Set(definedMap)
+ return nil
+}
+
+func getValueWithTag(t reflect.Type, tag string, opt options.Options) (interface{}, error) {
+ switch t.Kind() {
+ case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int8, reflect.Int16, reflect.Uint, reflect.Uint8,
+ reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64:
+ res, err := extractNumberFromTag(tag, t)
+ if err != nil {
+ return nil, err
+ }
+ return res, nil
+ case reflect.String:
+ res, err := extractStringFromTag(tag, opt)
+ if err != nil {
+ return nil, err
+ }
+ return res, nil
+ default:
+ return 0, errors.New(fakerErrors.ErrUnknownType)
+ }
+}
+
+func getNumberWithBoundary(t reflect.Type, boundary interfaces.RandomIntegerBoundary) (interface{}, error) {
+ switch t.Kind() {
+ case reflect.Uint:
+ return uint(randomIntegerWithBoundary(boundary)), nil
+ case reflect.Uint8:
+ return uint8(randomIntegerWithBoundary(boundary)), nil
+ case reflect.Uint16:
+ return uint16(randomIntegerWithBoundary(boundary)), nil
+ case reflect.Uint32:
+ return uint32(randomIntegerWithBoundary(boundary)), nil
+ case reflect.Uint64:
+ return uint64(randomIntegerWithBoundary(boundary)), nil
+ case reflect.Int:
+ return randomIntegerWithBoundary(boundary), nil
+ case reflect.Int8:
+ return int8(randomIntegerWithBoundary(boundary)), nil
+ case reflect.Int16:
+ return int16(randomIntegerWithBoundary(boundary)), nil
+ case reflect.Int32:
+ return int32(randomIntegerWithBoundary(boundary)), nil
+ case reflect.Int64:
+ return int64(randomIntegerWithBoundary(boundary)), nil
+ default:
+ return nil, errors.New(fakerErrors.ErrNotSupportedTypeForTag)
+ }
+}
+
+func getValueWithNoTag(t reflect.Type, opt options.Options) (interface{}, error) {
+ switch t.Kind() {
+ case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int8, reflect.Int16, reflect.Uint, reflect.Uint8,
+ reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64:
+ boundary := interfaces.RandomIntegerBoundary{
+ Start: opt.RandomIntegerBoundary.Start,
+ End: opt.RandomIntegerBoundary.End}
+ res, err := getNumberWithBoundary(t, boundary)
+ if err != nil {
+ return nil, err
+ }
+ return res, nil
+ case reflect.String:
+ res, err := randomString(opt.RandomStringLength, opt)
+ if err != nil {
+ return nil, err
+ }
+ return res, nil
+ default:
+ return 0, errors.New(fakerErrors.ErrUnknownType)
+ }
+}
+
+func userDefinedArray(v reflect.Value, tag string, opt options.Options) error {
+ tagFunc, tagExists := mapperTag.Load(tag)
+ if tagExists {
+ res, err := tagFunc(v)
+ if err != nil {
+ return err
+ }
+ v.Set(reflect.ValueOf(res))
+ return nil
+ }
+ sliceLen, err := extractSliceLengthFromTag(tag, opt)
+ if err != nil {
+ return err
+ }
+
+ if opt.SetSliceMapNilIfLenZero && sliceLen == 0 {
+ v.Set(reflect.Zero(v.Type()))
+ return nil
+ }
+ //remove slice_len from tag string to avoid extra logic in downstream function
+ tag = findSliceLenReg.ReplaceAllString(tag, "")
+ array := reflect.MakeSlice(v.Type(), sliceLen, sliceLen)
+ for i := 0; i < array.Len(); i++ {
+ k := v.Type().Elem().Kind()
+ if k == reflect.Pointer || k == reflect.Struct {
+ res, err := getFakedValue(array.Index(i).Interface(), &opt)
+ if err != nil {
+ return err
+ }
+ if res.Kind() == reflect.Invalid {
+ return fmt.Errorf("got invalid reflect value")
+ }
+ array.Index(i).Set(res)
+ continue
+ }
+ if tag == "" {
+ res, err := getValueWithNoTag(v.Type().Elem(), opt)
+ if err != nil {
+ return err
+ }
+ array.Index(i).Set(reflect.ValueOf(res))
+ continue
+ }
+
+ res, err := getValueWithTag(v.Type().Elem(), tag, opt)
+ if err != nil {
+ return err
+ }
+ array.Index(i).Set(reflect.ValueOf(res))
+ }
+ v.Set(array)
+ return nil
+}
+
+func userDefinedString(v reflect.Value, tag string, opt options.Options) error {
+ var res interface{}
+ var err error
+
+ if tagFunc, ok := mapperTag.Load(tag); ok {
+ res, err = tagFunc(v)
+ if err != nil {
+ return err
+ }
+ } else {
+ res, err = extractStringFromTag(tag, opt)
+ if err != nil {
+ return err
+ }
+ }
+ if res == nil {
+ return fmt.Errorf(fakerErrors.ErrTagNotSupported, tag)
+ }
+ val, _ := res.(string)
+ v.SetString(val)
+ return nil
+}
+
+func userDefinedNumber(v reflect.Value, tag string) error {
+ var res interface{}
+ var err error
+
+ if tagFunc, ok := mapperTag.Load(tag); ok {
+ res, err = tagFunc(v)
+ if err != nil {
+ return err
+ }
+ } else {
+ res, err = extractNumberFromTag(tag, v.Type())
+ if err != nil {
+ return err
+ }
+ }
+ if res == nil {
+ return fmt.Errorf(fakerErrors.ErrTagNotSupported, tag)
+ }
+
+ if v.CanSet() && v.CanConvert(v.Type()) {
+ v.Set(reflect.ValueOf(res).Convert(v.Type()))
+ }
+ return nil
+}
+
+// extractSliceLengthFromTag checks if the sliceLength tag 'slice_len' is set, if so, returns its value, else return a random length
+func extractSliceLengthFromTag(tag string, opt options.Options) (int, error) {
+ if strings.Contains(tag, SliceLength) {
+ lenParts := strings.Split(findSliceLenReg.FindString(tag), Equals)
+ if len(lenParts) != 2 {
+ return 0, fmt.Errorf(fakerErrors.ErrWrongFormattedTag, tag)
+ }
+ sliceLen, err := strconv.Atoi(lenParts[1])
+ if err != nil {
+ return 0, fmt.Errorf("the given sliceLength has to be numeric, tag: %s", tag)
+ }
+ if sliceLen < 0 {
+ return 0, fmt.Errorf("slice length can not be negative, tag: %s", tag)
+ }
+ return sliceLen, nil
+ }
+
+ return randomSliceAndMapSize(opt), nil //Returns random slice length if the sliceLength tag isn't set
+}
+
+func extractStringFromTag(tag string, opts options.Options) (interface{}, error) {
+ var err error
+ strlen := opts.RandomStringLength
+ strlng := opts.StringLanguage
+ isOneOfTag := strings.Contains(tag, ONEOF)
+ if !strings.Contains(tag, Length) && !strings.Contains(tag, Language) && !isOneOfTag {
+ return nil, fmt.Errorf(fakerErrors.ErrTagNotSupported, tag)
+ }
+ if strings.Contains(tag, Length) {
+ lenParts := strings.Split(findLenReg.FindString(tag), Equals)
+ if len(lenParts) != 2 {
+ return nil, fmt.Errorf(fakerErrors.ErrWrongFormattedTag, tag)
+ }
+ strlen, _ = strconv.Atoi(lenParts[1])
+ }
+ if strings.Contains(tag, Language) {
+ strlng, err = extractLangFromTag(tag)
+ if err != nil {
+ return nil, fmt.Errorf(fakerErrors.ErrWrongFormattedTag, tag)
+ }
+ }
+ if isOneOfTag {
+ var args []string
+ args, err = fetchOneOfArgsFromTag(tag)
+ if err != nil {
+ return nil, err
+ }
+ toRet := args[rand.Intn(len(args))]
+ return strings.TrimSpace(toRet), nil
+ }
+
+ copyOption := opts
+ copyOption.StringLanguage = strlng
+ res, err := randomString(strlen, copyOption)
+ return res, err
+}
+
+func extractLangFromTag(tag string) (*interfaces.LangRuneBoundary, error) {
+ text := findLangReg.FindString(tag)
+ texts := strings.Split(text, Equals)
+ if len(texts) != 2 {
+ return nil, fmt.Errorf(fakerErrors.ErrWrongFormattedTag, text)
+ }
+ switch strings.ToLower(texts[1]) {
+ case "eng":
+ return &interfaces.LangENG, nil
+ case "rus":
+ return &interfaces.LangRUS, nil
+ case "chi":
+ return &interfaces.LangCHI, nil
+ case "jpn":
+ return &interfaces.LangJPN, nil
+ case "kor":
+ return &interfaces.LangKOR, nil
+ case "emj":
+ return &interfaces.EmotEMJ, nil
+ default:
+ return &interfaces.LangENG, nil
+ }
+}
+
+func extractNumberFromTag(tag string, t reflect.Type) (interface{}, error) {
+ hasOneOf := strings.Contains(tag, ONEOF)
+ hasBoundaryStart := strings.Contains(tag, BoundaryStart)
+ hasBoundaryEnd := strings.Contains(tag, BoundaryEnd)
+ usingOneOfTag := hasOneOf && (!hasBoundaryStart && !hasBoundaryEnd)
+ usingBoundariesTags := !hasOneOf && (hasBoundaryStart && hasBoundaryEnd)
+ if !usingOneOfTag && !usingBoundariesTags {
+ return nil, fmt.Errorf(fakerErrors.ErrTagNotSupported, tag)
+ }
+
+ // handling oneof tag
+ if usingOneOfTag {
+ args, err := fetchOneOfArgsFromTag(tag)
+ if err != nil {
+ return nil, err
+ }
+ switch t.Kind() {
+ case reflect.Float64:
+ {
+ toRet, err := extractFloat64FromTagArgs(args)
+ if err != nil {
+ return nil, err
+ }
+ return toRet.(float64), nil
+ }
+ case reflect.Float32:
+ {
+ toRet, err := extractFloat32FromTagArgs(args)
+ if err != nil {
+ return nil, err
+ }
+ return toRet.(float32), nil
+ }
+ case reflect.Int64:
+ {
+ toRet, err := extractInt64FromTagArgs(args)
+ if err != nil {
+ return nil, err
+ }
+ return toRet.(int64), nil
+ }
+ case reflect.Int32:
+ {
+ toRet, err := extractInt32FromTagArgs(args)
+ if err != nil {
+ return nil, err
+ }
+ return toRet.(int32), nil
+ }
+ case reflect.Int16:
+ {
+ toRet, err := extractInt16FromTagArgs(args)
+ if err != nil {
+ return nil, err
+ }
+ return toRet.(int16), nil
+ }
+ case reflect.Int8:
+ {
+ toRet, err := extractInt8FromTagArgs(args)
+ if err != nil {
+ return nil, err
+ }
+ return toRet.(int8), nil
+ }
+ case reflect.Int:
+ {
+ toRet, err := extractIntFromTagArgs(args)
+ if err != nil {
+ return nil, err
+ }
+ return toRet.(int), nil
+ }
+ case reflect.Uint64:
+ {
+ toRet, err := extractUint64FromTagArgs(args)
+ if err != nil {
+ return nil, err
+ }
+ return toRet.(uint64), nil
+ }
+ case reflect.Uint32:
+ {
+ toRet, err := extractUint32FromTagArgs(args)
+ if err != nil {
+ return nil, err
+ }
+ return toRet.(uint32), nil
+ }
+ case reflect.Uint16:
+ {
+ toRet, err := extractUint16FromTagArgs(args)
+ if err != nil {
+ return nil, err
+ }
+ return toRet.(uint16), nil
+ }
+ case reflect.Uint8:
+ {
+ toRet, err := extractUint8FromTagArgs(args)
+ if err != nil {
+ return nil, err
+ }
+ return toRet.(uint8), nil
+ }
+ case reflect.Uint:
+ {
+ toRet, err := extractUintFromTagArgs(args)
+ if err != nil {
+ return nil, err
+ }
+ return toRet.(uint), nil
+ }
+ default:
+ {
+ return nil, fmt.Errorf("%s", fakerErrors.ErrUnsupportedNumberType)
+ }
+ }
+ }
+
+ // handling boundary tags
+ valuesStr := strings.Split(tag, comma)
+ if len(valuesStr) != 2 {
+ return nil, fmt.Errorf(fakerErrors.ErrWrongFormattedTag, tag)
+ }
+
+ // TODO(Xaspy): When Golang provides generics, we will be able to make this method simpler and more beautiful.
+ if t.Kind() == reflect.Float64 || t.Kind() == reflect.Float32 {
+ startBoundary, err := extractFloatFromText(valuesStr[0])
+ if err != nil {
+ return nil, err
+ }
+ endBoundary, err := extractFloatFromText(valuesStr[1])
+ if err != nil {
+ return nil, err
+ }
+ boundary := interfaces.RandomFloatBoundary{Start: startBoundary, End: endBoundary}
+ switch t.Kind() {
+ case reflect.Float32:
+ return float32(randomFloatWithBoundary(boundary)), nil
+ case reflect.Float64:
+ return randomFloatWithBoundary(boundary), nil
+ }
+ }
+
+ startBoundary, err := extractIntFromText(valuesStr[0])
+ if err != nil {
+ return nil, err
+ }
+ endBoundary, err := extractIntFromText(valuesStr[1])
+ if err != nil {
+ return nil, err
+ }
+ boundary := interfaces.RandomIntegerBoundary{Start: startBoundary, End: endBoundary}
+ return getNumberWithBoundary(t, boundary)
+}
+
+func extractIntFromText(text string) (int, error) {
+ text = strings.TrimSpace(text)
+ texts := strings.Split(text, Equals)
+ if len(texts) != 2 {
+ return 0, fmt.Errorf(fakerErrors.ErrWrongFormattedTag, text)
+ }
+ return strconv.Atoi(texts[1])
+}
+
+func extractFloatFromText(text string) (float64, error) {
+ text = strings.TrimSpace(text)
+ texts := strings.Split(text, Equals)
+ if len(texts) != 2 {
+ return 0, fmt.Errorf(fakerErrors.ErrWrongFormattedTag, text)
+ }
+ return strconv.ParseFloat(texts[1], 64)
+}
+
+func fetchOneOfArgsFromTag(tag string) ([]string, error) {
+ items := strings.Split(tag, colon)
+ argsList := items[1:]
+ if len(argsList) != 1 {
+ return nil, fmt.Errorf("%s", fakerErrors.ErrUnsupportedTagArguments)
+ }
+ if strings.Contains(argsList[0], ",,") {
+ return nil, fmt.Errorf("%s", fakerErrors.ErrDuplicateSeparator)
+ }
+ if argsList[0] == "" {
+ return nil, fmt.Errorf("%s", fakerErrors.ErrNotEnoughTagArguments)
+ }
+ args := strings.Split(argsList[0], comma)
+ if len(args) < 1 {
+ return nil, fmt.Errorf("%s", fakerErrors.ErrNotEnoughTagArguments)
+ }
+ return args, nil
+}
+
+func randomString(n int, fakerOpt options.Options) (string, error) {
+ b := make([]rune, 0)
+ set := make(map[rune]struct{})
+ if fakerOpt.StringLanguage.Exclude != nil {
+ for _, s := range fakerOpt.StringLanguage.Exclude {
+ set[s] = struct{}{}
+ }
+ }
+
+ counter := 0
+ for i := 0; i < n; {
+ randRune := rune(rand.Intn(int(fakerOpt.StringLanguage.End-fakerOpt.StringLanguage.Start)) + int(fakerOpt.StringLanguage.Start))
+ for slice.ContainsRune(set, randRune) {
+ if counter++; counter >= fakerOpt.MaxGenerateStringRetries {
+ return "", errors.New("max number of string generation retries exhausted")
+ }
+ randRune = rune(rand.Intn(int(fakerOpt.StringLanguage.End-fakerOpt.StringLanguage.Start)) + int(fakerOpt.StringLanguage.Start))
+ _, ok := set[randRune]
+ if !ok {
+ break
+ }
+ }
+ b = append(b, randRune)
+ i++
+ }
+
+ k := string(b)
+ return k, nil
+}
+
+// randomIntegerWithBoundary returns a random integer between input start and end boundary. [start, end)
+func randomIntegerWithBoundary(boundary interfaces.RandomIntegerBoundary) int {
+ span := boundary.End - boundary.Start
+ if span <= 0 {
+ return boundary.Start
+ }
+ return rand.Intn(span) + boundary.Start
+}
+
+// randomFloatWithBoundary returns a random float between input start and end boundary. [start, end)
+func randomFloatWithBoundary(boundary interfaces.RandomFloatBoundary) float64 {
+ span := boundary.End - boundary.Start
+ if span <= 0 {
+ return boundary.Start
+ }
+ return boundary.Start + rand.Float64()*span
+}
+
+// randomInteger returns a random integer between start and end boundary. [start, end)
+func randomInteger(opt *options.Options) int {
+ if opt == nil {
+ opt = options.DefaultOption()
+ }
+
+ return randomIntegerWithBoundary(*opt.RandomIntegerBoundary)
+}
+
+// randomFloat returns a random float between start and end boundary. [start, end)
+func randomFloat(opt *options.Options) float64 {
+ if opt == nil {
+ opt = options.DefaultOption()
+ }
+
+ return randomFloatWithBoundary(*opt.RandomFloatBoundary)
+}
+
+// randomSliceAndMapSize returns a random integer between [0,randomSliceAndMapSize). If the testRandZero is set, returns 0
+// Written for test purposes for shouldSetNil
+func randomSliceAndMapSize(opt options.Options) int {
+ if opt.SetSliceMapRandomToZero {
+ return 0
+ }
+ r := opt.RandomMaxSliceSize - opt.RandomMinSliceSize
+ if r < 1 {
+ r = 1
+ }
+ return opt.RandomMinSliceSize + rand.Intn(r)
+}
+
+func randomElementFromSliceString(s []string) string {
+ return s[rand.Int()%len(s)]
+}
+func randomStringNumber(n int) string {
+ b := make([]byte, n)
+ for i, cache, remain := n-1, rand.Int63(), letterIdxMax; i >= 0; {
+ if remain == 0 {
+ cache, remain = rand.Int63(), letterIdxMax
+ }
+ if idx := int(cache & letterIdxMask); idx < len(numberBytes) {
+ b[i] = numberBytes[idx]
+ i--
+ }
+ cache >>= letterIdxBits
+ remain--
+ }
+
+ return string(b)
+}
+
+// RandomInt Get three parameters , only first mandatory and the rest are optional
+// (minimum_int, maximum_int, count)
+//
+// If only set one parameter : An integer greater than minimum_int will be returned
+// If only set two parameters : All integers between minimum_int and maximum_int will be returned, in a random order.
+// If three parameters: `count` integers between minimum_int and maximum_int will be returned.
+func RandomInt(parameters ...int) (p []int, err error) {
+ switch len(parameters) {
+ case 1:
+ minInt := parameters[0]
+ p = rand.Perm(minInt)
+ for i := range p {
+ p[i] += minInt
+ }
+ case 2:
+ minInt, maxInt := parameters[0], parameters[1]
+ p = rand.Perm(maxInt - minInt + 1)
+
+ for i := range p {
+ p[i] += minInt
+ }
+ case 3:
+ minInt, maxInt := parameters[0], parameters[1]
+ count := parameters[2]
+ p = rand.Perm(maxInt - minInt + 1)
+
+ for i := range p {
+ p[i] += minInt
+ }
+ if len(p) > count {
+ p = p[0:count]
+ }
+ default:
+ err = fmt.Errorf(fakerErrors.ErrMoreArguments, len(parameters))
+ }
+ return p, err
+}
+
+func generateUnique(dataType string, fn func() interface{}) (interface{}, error) {
+ for i := 0; i < maxRetry; i++ {
+ value := fn()
+ uniqueVal, _ := uniqueValues.Load(dataType)
+ uniqueValArr, _ := uniqueVal.([]interface{})
+ if !slice.ContainsValue(uniqueValArr, value) { // Retry if unique value already found
+ uniqueValues.Store(dataType, append(uniqueValArr, value))
+ return value, nil
+ }
+ }
+ return reflect.Value{}, fmt.Errorf(fakerErrors.ErrUniqueFailure, dataType)
+}
+
+func singleFakeData(dataType string, fn func() interface{}, opts ...options.OptionFunc) interface{} {
+ ops := initOption(opts...)
+ if ops.GenerateUniqueValues {
+ v, err := generateUnique(dataType, fn)
+ if err != nil {
+ panic(err)
+ }
+ return v
+ }
+ return fn()
+}