84 lines
2.4 KiB
Go
84 lines
2.4 KiB
Go
|
package gofakeit
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"reflect"
|
||
|
)
|
||
|
|
||
|
// Fakeable is an interface that can be implemented by a type to provide a custom fake value.
|
||
|
type Fakeable interface {
|
||
|
// Fake returns a fake value for the type.
|
||
|
Fake(faker *Faker) (any, error)
|
||
|
}
|
||
|
|
||
|
func isFakeable(t reflect.Type) bool {
|
||
|
fakeableTyp := reflect.TypeOf((*Fakeable)(nil)).Elem()
|
||
|
|
||
|
return t.Implements(fakeableTyp) || reflect.PtrTo(t).Implements(fakeableTyp)
|
||
|
}
|
||
|
|
||
|
func callFake(faker *Faker, v reflect.Value, possibleKinds ...reflect.Kind) (any, error) {
|
||
|
f, ok := v.Addr().Interface().(Fakeable)
|
||
|
if !ok {
|
||
|
return nil, errors.New("not a Fakeable type")
|
||
|
}
|
||
|
|
||
|
fakedValue, err := f.Fake(faker)
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("error calling Fake: %w", err)
|
||
|
}
|
||
|
k := reflect.TypeOf(fakedValue).Kind()
|
||
|
if !containsKind(possibleKinds, k) {
|
||
|
return nil, fmt.Errorf("returned value kind %q is not amongst the valid ones: %v", k, possibleKinds)
|
||
|
}
|
||
|
|
||
|
switch k {
|
||
|
case reflect.String:
|
||
|
return reflect.ValueOf(fakedValue).String(), nil
|
||
|
case reflect.Bool:
|
||
|
return reflect.ValueOf(fakedValue).Bool(), nil
|
||
|
case reflect.Int:
|
||
|
return int(reflect.ValueOf(fakedValue).Int()), nil
|
||
|
case reflect.Int8:
|
||
|
return int8(reflect.ValueOf(fakedValue).Int()), nil
|
||
|
case reflect.Int16:
|
||
|
return int16(reflect.ValueOf(fakedValue).Int()), nil
|
||
|
case reflect.Int32:
|
||
|
return int32(reflect.ValueOf(fakedValue).Int()), nil
|
||
|
case reflect.Int64:
|
||
|
return int64(reflect.ValueOf(fakedValue).Int()), nil
|
||
|
case reflect.Uint:
|
||
|
return uint(reflect.ValueOf(fakedValue).Uint()), nil
|
||
|
case reflect.Uint8:
|
||
|
return uint8(reflect.ValueOf(fakedValue).Uint()), nil
|
||
|
case reflect.Uint16:
|
||
|
return uint16(reflect.ValueOf(fakedValue).Uint()), nil
|
||
|
case reflect.Uint32:
|
||
|
return uint32(reflect.ValueOf(fakedValue).Uint()), nil
|
||
|
case reflect.Uint64:
|
||
|
return uint64(reflect.ValueOf(fakedValue).Uint()), nil
|
||
|
case reflect.Float32:
|
||
|
return float32(reflect.ValueOf(fakedValue).Float()), nil
|
||
|
case reflect.Float64:
|
||
|
return float64(reflect.ValueOf(fakedValue).Float()), nil
|
||
|
case reflect.Slice:
|
||
|
return reflect.ValueOf(fakedValue).Interface(), nil
|
||
|
case reflect.Map:
|
||
|
return reflect.ValueOf(fakedValue).Interface(), nil
|
||
|
case reflect.Struct:
|
||
|
return reflect.ValueOf(fakedValue).Interface(), nil
|
||
|
default:
|
||
|
return nil, fmt.Errorf("unsupported type %q", k)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func containsKind(possibleKinds []reflect.Kind, kind reflect.Kind) bool {
|
||
|
for _, k := range possibleKinds {
|
||
|
if k == kind {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
return false
|
||
|
}
|