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

299 lines
4.8 KiB
Go
Raw Normal View History

2024-04-26 19:30:35 +00:00
package gofakeit
import (
"bytes"
"encoding/csv"
"encoding/json"
"errors"
"fmt"
"math/rand"
"reflect"
"strings"
)
// CSVOptions defines values needed for csv generation
2024-04-26 19:30:35 +00:00
type CSVOptions struct {
Delimiter string `json:"delimiter" xml:"delimiter" fake:"{randomstring:[,,tab]}"`
RowCount int `json:"row_count" xml:"row_count" fake:"{number:1,10}"`
Fields []Field `json:"fields" xml:"fields" fake:"{fields}"`
2024-04-26 19:30:35 +00:00
}
// CSV generates an object or an array of objects in json format
2024-04-26 19:30:35 +00:00
// A nil CSVOptions returns a randomly structured CSV.
2024-04-26 19:30:35 +00:00
func CSV(co *CSVOptions) ([]byte, error) { return csvFunc(globalFaker, co) }
// CSV generates an object or an array of objects in json format
2024-04-26 19:30:35 +00:00
// A nil CSVOptions returns a randomly structured CSV.
2024-04-26 19:30:35 +00:00
func (f *Faker) CSV(co *CSVOptions) ([]byte, error) { return csvFunc(f, co) }
func csvFunc(f *Faker, co *CSVOptions) ([]byte, error) {
2024-04-26 19:30:35 +00:00
if co == nil {
2024-04-26 19:30:35 +00:00
// We didn't get a CSVOptions, so create a new random one
2024-04-26 19:30:35 +00:00
err := f.Struct(&co)
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return nil, err
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
// Check delimiter
2024-04-26 19:30:35 +00:00
if co.Delimiter == "" {
2024-04-26 19:30:35 +00:00
co.Delimiter = ","
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
if strings.ToLower(co.Delimiter) == "tab" {
2024-04-26 19:30:35 +00:00
co.Delimiter = "\t"
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
if co.Delimiter != "," && co.Delimiter != "\t" && co.Delimiter != ";" {
2024-04-26 19:30:35 +00:00
return nil, errors.New("invalid delimiter type")
2024-04-26 19:30:35 +00:00
}
// Check fields
2024-04-26 19:30:35 +00:00
if co.Fields == nil || len(co.Fields) <= 0 {
2024-04-26 19:30:35 +00:00
return nil, errors.New("must pass fields in order to build json object(s)")
2024-04-26 19:30:35 +00:00
}
// Make sure you set a row count
2024-04-26 19:30:35 +00:00
if co.RowCount <= 0 {
2024-04-26 19:30:35 +00:00
return nil, errors.New("must have row count")
2024-04-26 19:30:35 +00:00
}
b := &bytes.Buffer{}
2024-04-26 19:30:35 +00:00
w := csv.NewWriter(b)
2024-04-26 19:30:35 +00:00
w.Comma = []rune(co.Delimiter)[0]
// Add header row
2024-04-26 19:30:35 +00:00
header := make([]string, len(co.Fields))
2024-04-26 19:30:35 +00:00
for i, field := range co.Fields {
2024-04-26 19:30:35 +00:00
header[i] = field.Name
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
w.Write(header)
// Loop through row count +1(for header) and add fields
2024-04-26 19:30:35 +00:00
for i := 1; i < co.RowCount+1; i++ {
2024-04-26 19:30:35 +00:00
vr := make([]string, len(co.Fields))
// Loop through fields and add to them to map[string]any
2024-04-26 19:30:35 +00:00
for ii, field := range co.Fields {
2024-04-26 19:30:35 +00:00
if field.Function == "autoincrement" {
2024-04-26 19:30:35 +00:00
vr[ii] = fmt.Sprintf("%d", i)
2024-04-26 19:30:35 +00:00
continue
2024-04-26 19:30:35 +00:00
}
// Get function info
2024-04-26 19:30:35 +00:00
funcInfo := GetFuncLookup(field.Function)
2024-04-26 19:30:35 +00:00
if funcInfo == nil {
2024-04-26 19:30:35 +00:00
return nil, errors.New("invalid function, " + field.Function + " does not exist")
2024-04-26 19:30:35 +00:00
}
value, err := funcInfo.Generate(f.Rand, &field.Params, funcInfo)
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return nil, err
2024-04-26 19:30:35 +00:00
}
if _, ok := value.([]byte); ok {
2024-04-26 19:30:35 +00:00
// If it's a slice of bytes or struct, unmarshal it into an interface
2024-04-26 19:30:35 +00:00
var v any
2024-04-26 19:30:35 +00:00
if err := json.Unmarshal(value.([]byte), &v); err != nil {
2024-04-26 19:30:35 +00:00
return nil, err
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
value = v
2024-04-26 19:30:35 +00:00
}
// If the value is a list of possible values, marsha it into a string
2024-04-26 19:30:35 +00:00
if reflect.TypeOf(value).Kind() == reflect.Struct ||
2024-04-26 19:30:35 +00:00
reflect.TypeOf(value).Kind() == reflect.Ptr ||
2024-04-26 19:30:35 +00:00
reflect.TypeOf(value).Kind() == reflect.Map ||
2024-04-26 19:30:35 +00:00
reflect.TypeOf(value).Kind() == reflect.Slice {
2024-04-26 19:30:35 +00:00
b, err := json.Marshal(value)
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return nil, err
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
value = string(b)
2024-04-26 19:30:35 +00:00
}
vr[ii] = fmt.Sprintf("%v", value)
2024-04-26 19:30:35 +00:00
}
w.Write(vr)
2024-04-26 19:30:35 +00:00
}
w.Flush()
if err := w.Error(); err != nil {
2024-04-26 19:30:35 +00:00
return nil, err
2024-04-26 19:30:35 +00:00
}
return b.Bytes(), nil
2024-04-26 19:30:35 +00:00
}
func addFileCSVLookup() {
2024-04-26 19:30:35 +00:00
AddFuncLookup("csv", Info{
Display: "CSV",
Category: "file",
2024-04-26 19:30:35 +00:00
Description: "Individual lines or data entries within a CSV (Comma-Separated Values) format",
2024-04-26 19:30:35 +00:00
Example: `id,first_name,last_name,password
2024-04-26 19:30:35 +00:00
1,Markus,Moen,Dc0VYXjkWABx
2024-04-26 19:30:35 +00:00
2,Osborne,Hilll,XPJ9OVNbs5lm`,
Output: "[]byte",
2024-04-26 19:30:35 +00:00
ContentType: "text/csv",
2024-04-26 19:30:35 +00:00
Params: []Param{
2024-04-26 19:30:35 +00:00
{Field: "delimiter", Display: "Delimiter", Type: "string", Default: ",", Description: "Separator in between row values"},
2024-04-26 19:30:35 +00:00
{Field: "rowcount", Display: "Row Count", Type: "int", Default: "100", Description: "Number of rows"},
2024-04-26 19:30:35 +00:00
{Field: "fields", Display: "Fields", Type: "[]Field", Description: "Fields containing key name and function"},
},
2024-04-26 19:30:35 +00:00
Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) {
2024-04-26 19:30:35 +00:00
co := CSVOptions{}
delimiter, err := info.GetString(m, "delimiter")
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return nil, err
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
co.Delimiter = delimiter
rowcount, err := info.GetInt(m, "rowcount")
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return nil, err
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
co.RowCount = rowcount
fieldsStr, err := info.GetStringArray(m, "fields")
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return nil, err
2024-04-26 19:30:35 +00:00
}
// Check to make sure fields has length
2024-04-26 19:30:35 +00:00
if len(fieldsStr) > 0 {
2024-04-26 19:30:35 +00:00
co.Fields = make([]Field, len(fieldsStr))
for i, f := range fieldsStr {
2024-04-26 19:30:35 +00:00
// Unmarshal fields string into fields array
2024-04-26 19:30:35 +00:00
err = json.Unmarshal([]byte(f), &co.Fields[i])
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return nil, err
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
f := &Faker{Rand: r}
2024-04-26 19:30:35 +00:00
csvOut, err := csvFunc(f, &co)
2024-04-26 19:30:35 +00:00
if err != nil {
2024-04-26 19:30:35 +00:00
return nil, err
2024-04-26 19:30:35 +00:00
}
return csvOut, nil
2024-04-26 19:30:35 +00:00
},
})
2024-04-26 19:30:35 +00:00
}