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

993 lines
14 KiB
Go
Raw Normal View History

2024-04-26 19:30:35 +00:00
package gofakeit
import (
"errors"
"fmt"
"reflect"
"strconv"
"strings"
"time"
)
// Struct fills in exported fields of a struct with random data
2024-04-26 19:30:35 +00:00
// based on the value of `fake` tag of exported fields
2024-04-26 19:30:35 +00:00
// or with the result of a call to the Fake() method
2024-04-26 19:30:35 +00:00
// if the field type implements `Fakeable`.
2024-04-26 19:30:35 +00:00
// Use `fake:"skip"` to explicitly skip an element.
2024-04-26 19:30:35 +00:00
// All built-in types are supported, with templating support
2024-04-26 19:30:35 +00:00
// for string types.
2024-04-26 19:30:35 +00:00
func Struct(v any) error { return structFunc(globalFaker, v) }
// Struct fills in exported fields of a struct with random data
2024-04-26 19:30:35 +00:00
// based on the value of `fake` tag of exported fields.
2024-04-26 19:30:35 +00:00
// Use `fake:"skip"` to explicitly skip an element.
2024-04-26 19:30:35 +00:00
// All built-in types are supported, with templating support
2024-04-26 19:30:35 +00:00
// for string types.
2024-04-26 19:30:35 +00:00
func (f *Faker) Struct(v any) error { return structFunc(f, v) }
func structFunc(f *Faker, v any) error {
2024-04-26 19:30:35 +00:00
return r(f, reflect.TypeOf(v), reflect.ValueOf(v), "", 0)
2024-04-26 19:30:35 +00:00
}
func r(f *Faker, t reflect.Type, v reflect.Value, tag string, size int) error {
2024-04-26 19:30:35 +00:00
// Handle special types
if t.PkgPath() == "encoding/json" {
2024-04-26 19:30:35 +00:00
// encoding/json has two special types:
2024-04-26 19:30:35 +00:00
// - RawMessage
2024-04-26 19:30:35 +00:00
// - Number
switch t.Name() {
2024-04-26 19:30:35 +00:00
case "RawMessage":
2024-04-26 19:30:35 +00:00
return rJsonRawMessage(f, t, v, tag, size)
2024-04-26 19:30:35 +00:00
case "Number":
2024-04-26 19:30:35 +00:00
return rJsonNumber(f, t, v, tag, size)
2024-04-26 19:30:35 +00:00
default:
2024-04-26 19:30:35 +00:00
return errors.New("unknown encoding/json type: " + t.Name())
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
// Handle generic types
2024-04-26 19:30:35 +00:00
switch t.Kind() {
2024-04-26 19:30:35 +00:00
case reflect.Ptr:
2024-04-26 19:30:35 +00:00
return rPointer(f, t, v, tag, size)
2024-04-26 19:30:35 +00:00
case reflect.Struct:
2024-04-26 19:30:35 +00:00
return rStruct(f, t, v, tag)
2024-04-26 19:30:35 +00:00
case reflect.String:
2024-04-26 19:30:35 +00:00
return rString(f, t, v, tag)
2024-04-26 19:30:35 +00:00
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
2024-04-26 19:30:35 +00:00
return rUint(f, t, v, tag)
2024-04-26 19:30:35 +00:00
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
2024-04-26 19:30:35 +00:00
return rInt(f, t, v, tag)
2024-04-26 19:30:35 +00:00
case reflect.Float32, reflect.Float64:
2024-04-26 19:30:35 +00:00
return rFloat(f, t, v, tag)
2024-04-26 19:30:35 +00:00
case reflect.Bool:
2024-04-26 19:30:35 +00:00
return rBool(f, t, v, tag)
2024-04-26 19:30:35 +00:00
case reflect.Array, reflect.Slice:
2024-04-26 19:30:35 +00:00
return rSlice(f, t, v, tag, size)
2024-04-26 19:30:35 +00:00
case reflect.Map:
2024-04-26 19:30:35 +00:00
return rMap(f, t, v, tag, size)
2024-04-26 19:30:35 +00:00
}
return nil
2024-04-26 19:30:35 +00:00
}
func rCustom(f *Faker, t reflect.Type, v reflect.Value, tag string) error {
2024-04-26 19:30:35 +00:00
// If tag is empty return error
2024-04-26 19:30:35 +00:00
if tag == "" {
2024-04-26 19:30:35 +00:00
return errors.New("tag is empty")
2024-04-26 19:30:35 +00:00
}
fName, fParams := parseNameAndParamsFromTag(tag)
2024-04-26 19:30:35 +00:00
info := GetFuncLookup(fName)
// Check to see if it's a replaceable lookup function
2024-04-26 19:30:35 +00:00
if info == nil {
2024-04-26 19:30:35 +00:00
return fmt.Errorf("function %q not found", tag)
2024-04-26 19:30:35 +00:00
}
// Parse map params
2024-04-26 19:30:35 +00:00
mapParams := parseMapParams(info, fParams)
// Call function
2024-04-26 19:30:35 +00:00
fValue, err := info.Generate(f.Rand, mapParams, info)
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return err
2024-04-26 19:30:35 +00:00
}
// Create new element of expected type
2024-04-26 19:30:35 +00:00
field := reflect.New(reflect.TypeOf(fValue))
2024-04-26 19:30:35 +00:00
field.Elem().Set(reflect.ValueOf(fValue))
// Check if element is pointer if so
2024-04-26 19:30:35 +00:00
// grab the underlying value
2024-04-26 19:30:35 +00:00
fieldElem := field.Elem()
2024-04-26 19:30:35 +00:00
if fieldElem.Kind() == reflect.Ptr {
2024-04-26 19:30:35 +00:00
fieldElem = fieldElem.Elem()
2024-04-26 19:30:35 +00:00
}
// Check if field kind is the same as the expected type
2024-04-26 19:30:35 +00:00
if fieldElem.Kind() != v.Kind() {
2024-04-26 19:30:35 +00:00
// return error saying the field and kinds that do not match
2024-04-26 19:30:35 +00:00
return errors.New("field kind " + fieldElem.Kind().String() + " does not match expected kind " + v.Kind().String())
2024-04-26 19:30:35 +00:00
}
// Set the value
2024-04-26 19:30:35 +00:00
v.Set(fieldElem.Convert(v.Type()))
// If a function is called to set the struct
2024-04-26 19:30:35 +00:00
// stop from going through sub fields
2024-04-26 19:30:35 +00:00
return nil
2024-04-26 19:30:35 +00:00
}
func rStruct(f *Faker, t reflect.Type, v reflect.Value, tag string) error {
2024-04-26 19:30:35 +00:00
// Check if tag exists, if so run custom function
2024-04-26 19:30:35 +00:00
if t.Name() != "" && tag != "" {
2024-04-26 19:30:35 +00:00
return rCustom(f, t, v, tag)
2024-04-26 19:30:35 +00:00
}
// Check if struct is fakeable
2024-04-26 19:30:35 +00:00
if isFakeable(t) {
2024-04-26 19:30:35 +00:00
value, err := callFake(f, v, reflect.Struct)
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return err
2024-04-26 19:30:35 +00:00
}
v.Set(reflect.ValueOf(value))
2024-04-26 19:30:35 +00:00
return nil
2024-04-26 19:30:35 +00:00
}
// Loop through all the fields of the struct
2024-04-26 19:30:35 +00:00
n := t.NumField()
2024-04-26 19:30:35 +00:00
for i := 0; i < n; i++ {
2024-04-26 19:30:35 +00:00
elementT := t.Field(i)
2024-04-26 19:30:35 +00:00
elementV := v.Field(i)
2024-04-26 19:30:35 +00:00
fakeTag, ok := elementT.Tag.Lookup("fake")
// Check whether or not to skip this field
2024-04-26 19:30:35 +00:00
if ok && fakeTag == "skip" || fakeTag == "-" {
2024-04-26 19:30:35 +00:00
// Do nothing, skip it
2024-04-26 19:30:35 +00:00
continue
2024-04-26 19:30:35 +00:00
}
// Check to make sure you can set it or that it's an embedded(anonymous) field
2024-04-26 19:30:35 +00:00
if !elementV.CanSet() && !elementT.Anonymous {
2024-04-26 19:30:35 +00:00
continue
2024-04-26 19:30:35 +00:00
}
// Check if reflect type is of values we can specifically set
2024-04-26 19:30:35 +00:00
elemStr := elementT.Type.String()
2024-04-26 19:30:35 +00:00
switch elemStr {
2024-04-26 19:30:35 +00:00
case "time.Time", "*time.Time":
2024-04-26 19:30:35 +00:00
// Check if element is a pointer
2024-04-26 19:30:35 +00:00
elemV := elementV
2024-04-26 19:30:35 +00:00
if elemStr == "*time.Time" {
2024-04-26 19:30:35 +00:00
elemV = reflect.New(elementT.Type.Elem()).Elem()
2024-04-26 19:30:35 +00:00
}
// Run rTime on the element
2024-04-26 19:30:35 +00:00
err := rTime(f, elementT, elemV, fakeTag)
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return err
2024-04-26 19:30:35 +00:00
}
if elemStr == "*time.Time" {
2024-04-26 19:30:35 +00:00
elementV.Set(elemV.Addr())
2024-04-26 19:30:35 +00:00
}
continue
2024-04-26 19:30:35 +00:00
}
// Check if fakesize is set
2024-04-26 19:30:35 +00:00
size := -1 // Set to -1 to indicate fakesize was not set
2024-04-26 19:30:35 +00:00
fs, ok := elementT.Tag.Lookup("fakesize")
2024-04-26 19:30:35 +00:00
if ok {
2024-04-26 19:30:35 +00:00
var err error
// Check if size has params separated by ,
2024-04-26 19:30:35 +00:00
if strings.Contains(fs, ",") {
2024-04-26 19:30:35 +00:00
sizeSplit := strings.SplitN(fs, ",", 2)
2024-04-26 19:30:35 +00:00
if len(sizeSplit) == 2 {
2024-04-26 19:30:35 +00:00
var sizeMin int
2024-04-26 19:30:35 +00:00
var sizeMax int
sizeMin, err = strconv.Atoi(sizeSplit[0])
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return err
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
sizeMax, err = strconv.Atoi(sizeSplit[1])
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return err
2024-04-26 19:30:35 +00:00
}
size = f.Rand.Intn(sizeMax-sizeMin+1) + sizeMin
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
size, err = strconv.Atoi(fs)
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return 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
}
// Recursively call r() to fill in the struct
2024-04-26 19:30:35 +00:00
err := r(f, elementT.Type, elementV, fakeTag, size)
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return err
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
return nil
2024-04-26 19:30:35 +00:00
}
func rPointer(f *Faker, t reflect.Type, v reflect.Value, tag string, size int) error {
2024-04-26 19:30:35 +00:00
elemT := t.Elem()
2024-04-26 19:30:35 +00:00
if v.IsNil() {
2024-04-26 19:30:35 +00:00
nv := reflect.New(elemT).Elem()
2024-04-26 19:30:35 +00:00
err := r(f, elemT, nv, tag, size)
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return err
2024-04-26 19:30:35 +00:00
}
v.Set(nv.Addr())
2024-04-26 19:30:35 +00:00
} else {
2024-04-26 19:30:35 +00:00
err := r(f, elemT, v.Elem(), tag, size)
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return err
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
return nil
2024-04-26 19:30:35 +00:00
}
func rSlice(f *Faker, t reflect.Type, v reflect.Value, tag string, size int) error {
2024-04-26 19:30:35 +00:00
// If you cant even set it dont even try
2024-04-26 19:30:35 +00:00
if !v.CanSet() {
2024-04-26 19:30:35 +00:00
return errors.New("cannot set slice")
2024-04-26 19:30:35 +00:00
}
// Check if tag exists, if so run custom function
2024-04-26 19:30:35 +00:00
if t.Name() != "" && tag != "" {
2024-04-26 19:30:35 +00:00
// Check to see if custom function works if not continue to normal loop of values
2024-04-26 19:30:35 +00:00
err := rCustom(f, t, v, tag)
2024-04-26 19:30:35 +00:00
if err == nil {
2024-04-26 19:30:35 +00:00
return nil
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
} else if isFakeable(t) {
2024-04-26 19:30:35 +00:00
value, err := callFake(f, v, reflect.Slice)
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return err
2024-04-26 19:30:35 +00:00
}
v.Set(reflect.ValueOf(value))
2024-04-26 19:30:35 +00:00
return nil
2024-04-26 19:30:35 +00:00
}
// Grab original size to use if needed for sub arrays
2024-04-26 19:30:35 +00:00
ogSize := size
// If the value has a len and is less than the size
2024-04-26 19:30:35 +00:00
// use that instead of the requested size
2024-04-26 19:30:35 +00:00
elemLen := v.Len()
2024-04-26 19:30:35 +00:00
if elemLen == 0 && size == -1 {
2024-04-26 19:30:35 +00:00
size = number(f.Rand, 1, 10)
2024-04-26 19:30:35 +00:00
} else if elemLen != 0 && (size == -1 || elemLen < size) {
2024-04-26 19:30:35 +00:00
size = elemLen
2024-04-26 19:30:35 +00:00
}
// Get the element type
2024-04-26 19:30:35 +00:00
elemT := t.Elem()
// Loop through the elements length and set based upon the index
2024-04-26 19:30:35 +00:00
for i := 0; i < size; i++ {
2024-04-26 19:30:35 +00:00
nv := reflect.New(elemT)
2024-04-26 19:30:35 +00:00
err := r(f, elemT, nv.Elem(), tag, ogSize)
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return err
2024-04-26 19:30:35 +00:00
}
// If values are already set fill them up, otherwise append
2024-04-26 19:30:35 +00:00
if elemLen != 0 {
2024-04-26 19:30:35 +00:00
v.Index(i).Set(reflect.Indirect(nv))
2024-04-26 19:30:35 +00:00
} else {
2024-04-26 19:30:35 +00:00
v.Set(reflect.Append(reflect.Indirect(v), reflect.Indirect(nv)))
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
return nil
2024-04-26 19:30:35 +00:00
}
func rMap(f *Faker, t reflect.Type, v reflect.Value, tag string, size int) error {
2024-04-26 19:30:35 +00:00
// If you cant even set it dont even try
2024-04-26 19:30:35 +00:00
if !v.CanSet() {
2024-04-26 19:30:35 +00:00
return errors.New("cannot set slice")
2024-04-26 19:30:35 +00:00
}
// Check if tag exists, if so run custom function
2024-04-26 19:30:35 +00:00
if tag != "" {
2024-04-26 19:30:35 +00:00
return rCustom(f, t, v, tag)
2024-04-26 19:30:35 +00:00
} else if size > 0 {
2024-04-26 19:30:35 +00:00
// NOOP
2024-04-26 19:30:35 +00:00
} else if isFakeable(t) {
2024-04-26 19:30:35 +00:00
value, err := callFake(f, v, reflect.Map)
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return err
2024-04-26 19:30:35 +00:00
}
v.Set(reflect.ValueOf(value))
2024-04-26 19:30:35 +00:00
return nil
2024-04-26 19:30:35 +00:00
}
// Set a size
2024-04-26 19:30:35 +00:00
newSize := size
2024-04-26 19:30:35 +00:00
if newSize == -1 {
2024-04-26 19:30:35 +00:00
newSize = number(f.Rand, 1, 10)
2024-04-26 19:30:35 +00:00
}
// Create new map based upon map key value type
2024-04-26 19:30:35 +00:00
mapType := reflect.MapOf(t.Key(), t.Elem())
2024-04-26 19:30:35 +00:00
newMap := reflect.MakeMap(mapType)
for i := 0; i < newSize; i++ {
2024-04-26 19:30:35 +00:00
// Create new key
2024-04-26 19:30:35 +00:00
mapIndex := reflect.New(t.Key())
2024-04-26 19:30:35 +00:00
err := r(f, t.Key(), mapIndex.Elem(), "", -1)
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return err
2024-04-26 19:30:35 +00:00
}
// Create new value
2024-04-26 19:30:35 +00:00
mapValue := reflect.New(t.Elem())
2024-04-26 19:30:35 +00:00
err = r(f, t.Elem(), mapValue.Elem(), "", -1)
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return err
2024-04-26 19:30:35 +00:00
}
newMap.SetMapIndex(mapIndex.Elem(), mapValue.Elem())
2024-04-26 19:30:35 +00:00
}
// Set newMap into struct field
2024-04-26 19:30:35 +00:00
if t.Kind() == reflect.Ptr {
2024-04-26 19:30:35 +00:00
v.Set(newMap.Elem())
2024-04-26 19:30:35 +00:00
} else {
2024-04-26 19:30:35 +00:00
v.Set(newMap)
2024-04-26 19:30:35 +00:00
}
return nil
2024-04-26 19:30:35 +00:00
}
func rString(f *Faker, t reflect.Type, v reflect.Value, tag string) error {
2024-04-26 19:30:35 +00:00
if tag != "" {
2024-04-26 19:30:35 +00:00
v.SetString(generate(f.Rand, tag))
2024-04-26 19:30:35 +00:00
} else if isFakeable(t) {
2024-04-26 19:30:35 +00:00
value, err := callFake(f, v, reflect.String)
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return err
2024-04-26 19:30:35 +00:00
}
valueStr, ok := value.(string)
2024-04-26 19:30:35 +00:00
if !ok {
2024-04-26 19:30:35 +00:00
return errors.New("call to Fake method did not return a string")
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
v.SetString(valueStr)
2024-04-26 19:30:35 +00:00
} else {
2024-04-26 19:30:35 +00:00
v.SetString(generate(f.Rand, strings.Repeat("?", number(f.Rand, 4, 10))))
2024-04-26 19:30:35 +00:00
}
return nil
2024-04-26 19:30:35 +00:00
}
func rInt(f *Faker, t reflect.Type, v reflect.Value, tag string) error {
2024-04-26 19:30:35 +00:00
if tag != "" {
2024-04-26 19:30:35 +00:00
i, err := strconv.ParseInt(generate(f.Rand, tag), 10, 64)
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return err
2024-04-26 19:30:35 +00:00
}
v.SetInt(i)
2024-04-26 19:30:35 +00:00
} else if isFakeable(t) {
2024-04-26 19:30:35 +00:00
value, err := callFake(f, v, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64)
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return err
2024-04-26 19:30:35 +00:00
}
switch i := value.(type) {
2024-04-26 19:30:35 +00:00
case int:
2024-04-26 19:30:35 +00:00
v.SetInt(int64(i))
2024-04-26 19:30:35 +00:00
case int8:
2024-04-26 19:30:35 +00:00
v.SetInt(int64(i))
2024-04-26 19:30:35 +00:00
case int16:
2024-04-26 19:30:35 +00:00
v.SetInt(int64(i))
2024-04-26 19:30:35 +00:00
case int32:
2024-04-26 19:30:35 +00:00
v.SetInt(int64(i))
2024-04-26 19:30:35 +00:00
case int64:
2024-04-26 19:30:35 +00:00
v.SetInt(int64(i))
2024-04-26 19:30:35 +00:00
default:
2024-04-26 19:30:35 +00:00
return errors.New("call to Fake method did not return an integer")
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
// If no tag or error converting to int, set with random value
2024-04-26 19:30:35 +00:00
switch t.Kind() {
2024-04-26 19:30:35 +00:00
case reflect.Int:
2024-04-26 19:30:35 +00:00
v.SetInt(int64Func(f.Rand))
2024-04-26 19:30:35 +00:00
case reflect.Int8:
2024-04-26 19:30:35 +00:00
v.SetInt(int64(int8Func(f.Rand)))
2024-04-26 19:30:35 +00:00
case reflect.Int16:
2024-04-26 19:30:35 +00:00
v.SetInt(int64(int16Func(f.Rand)))
2024-04-26 19:30:35 +00:00
case reflect.Int32:
2024-04-26 19:30:35 +00:00
v.SetInt(int64(int32Func(f.Rand)))
2024-04-26 19:30:35 +00:00
case reflect.Int64:
2024-04-26 19:30:35 +00:00
v.SetInt(int64Func(f.Rand))
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
return nil
2024-04-26 19:30:35 +00:00
}
func rUint(f *Faker, t reflect.Type, v reflect.Value, tag string) error {
2024-04-26 19:30:35 +00:00
if tag != "" {
2024-04-26 19:30:35 +00:00
u, err := strconv.ParseUint(generate(f.Rand, tag), 10, 64)
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return err
2024-04-26 19:30:35 +00:00
}
v.SetUint(u)
2024-04-26 19:30:35 +00:00
} else if isFakeable(t) {
2024-04-26 19:30:35 +00:00
value, err := callFake(f, v, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64)
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return err
2024-04-26 19:30:35 +00:00
}
switch i := value.(type) {
2024-04-26 19:30:35 +00:00
case uint:
2024-04-26 19:30:35 +00:00
v.SetUint(uint64(i))
2024-04-26 19:30:35 +00:00
case uint8:
2024-04-26 19:30:35 +00:00
v.SetUint(uint64(i))
2024-04-26 19:30:35 +00:00
case uint16:
2024-04-26 19:30:35 +00:00
v.SetUint(uint64(i))
2024-04-26 19:30:35 +00:00
case uint32:
2024-04-26 19:30:35 +00:00
v.SetUint(uint64(i))
2024-04-26 19:30:35 +00:00
case uint64:
2024-04-26 19:30:35 +00:00
v.SetUint(uint64(i))
2024-04-26 19:30:35 +00:00
default:
2024-04-26 19:30:35 +00:00
return errors.New("call to Fake method did not return an unsigned integer")
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
// If no tag or error converting to uint, set with random value
2024-04-26 19:30:35 +00:00
switch t.Kind() {
2024-04-26 19:30:35 +00:00
case reflect.Uint:
2024-04-26 19:30:35 +00:00
v.SetUint(uint64Func(f.Rand))
2024-04-26 19:30:35 +00:00
case reflect.Uint8:
2024-04-26 19:30:35 +00:00
v.SetUint(uint64(uint8Func(f.Rand)))
2024-04-26 19:30:35 +00:00
case reflect.Uint16:
2024-04-26 19:30:35 +00:00
v.SetUint(uint64(uint16Func(f.Rand)))
2024-04-26 19:30:35 +00:00
case reflect.Uint32:
2024-04-26 19:30:35 +00:00
v.SetUint(uint64(uint32Func(f.Rand)))
2024-04-26 19:30:35 +00:00
case reflect.Uint64:
2024-04-26 19:30:35 +00:00
v.SetUint(uint64Func(f.Rand))
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
return nil
2024-04-26 19:30:35 +00:00
}
func rFloat(f *Faker, t reflect.Type, v reflect.Value, tag string) error {
2024-04-26 19:30:35 +00:00
if tag != "" {
2024-04-26 19:30:35 +00:00
f, err := strconv.ParseFloat(generate(f.Rand, tag), 64)
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return err
2024-04-26 19:30:35 +00:00
}
v.SetFloat(f)
2024-04-26 19:30:35 +00:00
} else if isFakeable(t) {
2024-04-26 19:30:35 +00:00
value, err := callFake(f, v, reflect.Float32, reflect.Float64)
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return err
2024-04-26 19:30:35 +00:00
}
switch i := value.(type) {
2024-04-26 19:30:35 +00:00
case float32:
2024-04-26 19:30:35 +00:00
v.SetFloat(float64(i))
2024-04-26 19:30:35 +00:00
case float64:
2024-04-26 19:30:35 +00:00
v.SetFloat(float64(i))
2024-04-26 19:30:35 +00:00
default:
2024-04-26 19:30:35 +00:00
return errors.New("call to Fake method did not return a float")
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
// If no tag or error converting to float, set with random value
2024-04-26 19:30:35 +00:00
switch t.Kind() {
2024-04-26 19:30:35 +00:00
case reflect.Float64:
2024-04-26 19:30:35 +00:00
v.SetFloat(float64Func(f.Rand))
2024-04-26 19:30:35 +00:00
case reflect.Float32:
2024-04-26 19:30:35 +00:00
v.SetFloat(float64(float32Func(f.Rand)))
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
return nil
2024-04-26 19:30:35 +00:00
}
func rBool(f *Faker, t reflect.Type, v reflect.Value, tag string) error {
2024-04-26 19:30:35 +00:00
if tag != "" {
2024-04-26 19:30:35 +00:00
b, err := strconv.ParseBool(generate(f.Rand, tag))
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return err
2024-04-26 19:30:35 +00:00
}
v.SetBool(b)
2024-04-26 19:30:35 +00:00
} else if isFakeable(t) {
2024-04-26 19:30:35 +00:00
value, err := callFake(f, v, reflect.Bool)
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return err
2024-04-26 19:30:35 +00:00
}
switch i := value.(type) {
2024-04-26 19:30:35 +00:00
case bool:
2024-04-26 19:30:35 +00:00
v.SetBool(bool(i))
2024-04-26 19:30:35 +00:00
default:
2024-04-26 19:30:35 +00:00
return errors.New("call to Fake method did not return a boolean")
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
// If no tag or error converting to boolean, set with random value
2024-04-26 19:30:35 +00:00
v.SetBool(boolFunc(f.Rand))
2024-04-26 19:30:35 +00:00
}
return nil
2024-04-26 19:30:35 +00:00
}
// rTime will set a time.Time field the best it can from either the default date tag or from the generate tag
2024-04-26 19:30:35 +00:00
func rTime(f *Faker, t reflect.StructField, v reflect.Value, tag string) error {
2024-04-26 19:30:35 +00:00
if tag != "" {
2024-04-26 19:30:35 +00:00
// Generate time
2024-04-26 19:30:35 +00:00
timeOutput := generate(f.Rand, tag)
// Check to see if timeOutput has monotonic clock reading
2024-04-26 19:30:35 +00:00
// if so, remove it. This is because time.Parse() does not
2024-04-26 19:30:35 +00:00
// support parsing the monotonic clock reading
2024-04-26 19:30:35 +00:00
if strings.Contains(timeOutput, " m=") {
2024-04-26 19:30:35 +00:00
timeOutput = strings.Split(timeOutput, " m=")[0]
2024-04-26 19:30:35 +00:00
}
// Check to see if they are passing in a format to parse the time
2024-04-26 19:30:35 +00:00
timeFormat, timeFormatOK := t.Tag.Lookup("format")
2024-04-26 19:30:35 +00:00
if timeFormatOK {
2024-04-26 19:30:35 +00:00
timeFormat = javaDateFormatToGolangDateFormat(timeFormat)
2024-04-26 19:30:35 +00:00
} else {
2024-04-26 19:30:35 +00:00
// If tag == "{date}" use time.RFC3339
2024-04-26 19:30:35 +00:00
// They are attempting to use the default date lookup
2024-04-26 19:30:35 +00:00
if tag == "{date}" {
2024-04-26 19:30:35 +00:00
timeFormat = time.RFC3339
2024-04-26 19:30:35 +00:00
} else {
2024-04-26 19:30:35 +00:00
// Default format of time.Now().String()
2024-04-26 19:30:35 +00:00
timeFormat = "2006-01-02 15:04:05.999999999 -0700 MST"
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
// If output is larger than format cut the output
2024-04-26 19:30:35 +00:00
// This helps us avoid errors from time.Parse
2024-04-26 19:30:35 +00:00
if len(timeOutput) > len(timeFormat) {
2024-04-26 19:30:35 +00:00
timeOutput = timeOutput[:len(timeFormat)]
2024-04-26 19:30:35 +00:00
}
// Attempt to parse the time
2024-04-26 19:30:35 +00:00
timeStruct, err := time.Parse(timeFormat, timeOutput)
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return err
2024-04-26 19:30:35 +00:00
}
v.Set(reflect.ValueOf(timeStruct))
2024-04-26 19:30:35 +00:00
return nil
2024-04-26 19:30:35 +00:00
}
v.Set(reflect.ValueOf(date(f.Rand)))
2024-04-26 19:30:35 +00:00
return nil
2024-04-26 19:30:35 +00:00
}