From 6960aecc25400320adee1b8802a86839326e15b6 Mon Sep 17 00:00:00 2001 From: Mitja Felicijan Date: Thu, 5 Feb 2026 00:37:32 +0100 Subject: Engage! --- vendor/github.com/go-faker/faker/v4/faker.go | 1412 ++++++++++++++++++++++++++ 1 file changed, 1412 insertions(+) create mode 100644 vendor/github.com/go-faker/faker/v4/faker.go (limited to 'vendor/github.com/go-faker/faker/v4/faker.go') 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< 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() +} -- cgit v1.2.3