Skip to content

Commit

Permalink
mv builder funcs
Browse files Browse the repository at this point in the history
  • Loading branch information
mitchs-dev committed Sep 5, 2024
1 parent 30ccbd1 commit f1c4304
Showing 1 changed file with 8 additions and 148 deletions.
156 changes: 8 additions & 148 deletions build-struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,35 +8,10 @@ Usage:
package main

import (
"encoding/json"
"fmt"
"math"
"os"
"strings"

"gopkg.in/yaml.v2"
)

// Static variables
var (
// Variable for the file type - JSON
ftJSON = "json"
// Variable for the file type - YAML
ftYAML = "yaml"
)

// Dynamic variables
var (
// structName is the name of the struct
structName string
// The path to the file
filePath string
// The file type of the provided file (JSON or YAML)
fileType string
// The data from the file
mappedFileData map[interface{}]interface{}
// structOutput is the output of the struct
structOutput string
"github.com/mitchs-dev/build-struct/pkg/builder"
)

func init() {
Expand All @@ -48,25 +23,25 @@ func init() {
}

// Set the struct name
structName = os.Args[1]
builder.StructName = os.Args[1]

// Set the file path
filePath = os.Args[2]
builder.FilePath = os.Args[2]

// Make sure that the file exists
if _, err := os.Stat(filePath); os.IsNotExist(err) {
if _, err := os.Stat(builder.FilePath); os.IsNotExist(err) {
fmt.Println("Error: The provided file does not exist.")
os.Exit(1)
}

// Make sure that the file is not empty
if _, err := os.Stat(filePath); os.IsNotExist(err) {
if _, err := os.Stat(builder.FilePath); os.IsNotExist(err) {
fmt.Println("Error: The file is empty.")
os.Exit(1)
}

// Make sure that it's a file and not a directory
if fileInfo, err := os.Stat(filePath); err == nil && fileInfo.IsDir() {
if fileInfo, err := os.Stat(builder.FilePath); err == nil && fileInfo.IsDir() {
fmt.Println("Error: The provided path is a directory.")
os.Exit(1)
}
Expand All @@ -75,8 +50,8 @@ func init() {

func main() {

determineFileType()
structOutput := buildStructFromData()
builder.DetermineFileType()
structOutput := builder.BuildStructFromData()

// Return the struct output if it was built successfully
if structOutput != "" {
Expand All @@ -88,118 +63,3 @@ func main() {
}

}

// determineFileType determines the file type of the provided file
func determineFileType() {
// Read the file
fileData, err := os.ReadFile(filePath)
if err != nil {
fmt.Println("Error: Could not read the file.")
os.Exit(1)
}

// Try to unmarshal the data into a map[interface{}]interface{}
var data map[interface{}]interface{}
jsonErr := json.Unmarshal(fileData, &data)
yamlErr := yaml.Unmarshal(fileData, &data)

// If JSON unmarshalling was successful, set the file type to JSON
if jsonErr == nil {
fileType = ftJSON
mappedFileData = data
return
}

// If YAML unmarshalling was successful, set the file type to YAML
if yamlErr == nil {
fileType = ftYAML
mappedFileData = data
return
}

// Otherwise, the file type is unsupported
fmt.Println("Unsupported file type.")
os.Exit(1)
}

// buildStructFromData builds a struct from the YAML data
func buildStructFromData() string {
// Create a struct from the YAML data
structOutput = "type " + structName + " struct {\n"
structOutput += structBuilder(mappedFileData, "\t")
structOutput += "}"

return structOutput
}

// structBuilder builds a struct from the provided data
func structBuilder(data map[interface{}]interface{}, prefix string) string {
// Initialize the struct fields
var structFields string

// Iterate over the data
for key, value := range data {
// Get the type of the value
var fieldType string

// Check the type of the value
switch v := value.(type) {
case map[interface{}]interface{}:
fieldType = "struct {\n" + structBuilder(v, prefix+"\t") + prefix + "}"
case []interface{}:
if len(v) > 0 {
// Check if the first element is a map
if _, ok := v[0].(map[interface{}]interface{}); ok {
// If it's a map, generate a slice of structs
fieldType = "[]struct {\n" + structBuilder(v[0].(map[interface{}]interface{}), prefix+"\t") + prefix + "}"
} else {
// If it's not a map, use the existing logic
types := make(map[string]bool)
for _, elem := range v {
types[getType(elem)] = true
}
if len(types) == 1 {
for t := range types {
fieldType = "[]" + t
}
} else {
fieldType = "[]interface{}"
}
}
} else {
fieldType = "[]interface{}"
}
default:
fieldType = getType(v)
}
keyStr := fmt.Sprintf("%v", key)
structFields += prefix + fmt.Sprintf("%s %s `"+fileType+":\"%s\"`\n", strings.Title(keyStr), fieldType, key)
}

return structFields
}

// getType returns the type of the provided value
func getType(v interface{}) string {
switch v := v.(type) {
case string:
return "string"
case float64:
return "float64"
case int:
if math.Abs(float64(v)) > math.MaxInt32 {
return "int64"
} else {
return "int"
}
case bool:
return "bool"
case []interface{}:
return "[]interface{}"
case map[interface{}]interface{}:
return "struct {\n" + structBuilder(v, "\t") + "}\n"

default:
return "interface{}"
}
}

0 comments on commit f1c4304

Please # to comment.