func ExampleGetFieldKind() {
	s := MyStruct{
		FirstField:  "first value",
		SecondField: 2,
		ThirdField:  "third value",
	}

	var firstFieldKind reflect.Kind
	var secondFieldKind reflect.Kind
	var err error

	// GetFieldKind will return reflect.String
	firstFieldKind, err = reflections.GetFieldKind(s, "FirstField")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(firstFieldKind)

	// GetFieldKind will return reflect.Int
	secondFieldKind, err = reflections.GetFieldKind(s, "SecondField")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(secondFieldKind)
}
Beispiel #2
0
func (r *Row) Bind(x interface{}, strategy map[string]string) error {

	for src, dest := range strategy {

		data, ok := r.data[src]

		if ok {
			k, err := reflections.GetFieldKind(x, dest)
			if err != nil {
				return err
			}

			switch k {
			case reflect.String:
				{
					reflections.SetField(x, dest, data)
				}
			case reflect.Int64:
				{
					i, err := strconv.ParseInt(data, 10, 64)
					if err != nil {
						return err
					}
					reflections.SetField(x, dest, i)
				}
			case reflect.Ptr:
				{
					value, err := reflections.GetField(x, dest)
					if err != nil {
						return err
					}
					if reflect.TypeOf(value) == typeDec {
						dec, success := new(inf.Dec).SetString(data)
						if !success {
							fmt.Errorf("Could not parse inf.Dec: %s", data)
						}
						reflections.SetField(x, dest, dec)
					}
				}
			case reflect.Struct:
				{
					value, err := reflections.GetField(x, dest)
					if err != nil {
						return err
					}
					if reflect.TypeOf(value) == typeTime {
						date, err := time.ParseInLocation("2006-01-02 15:04:05", data, r.opts.TimeZone)
						if err != nil {
							return err
						}
						reflections.SetField(x, dest, date)
					}
				}
			}
		}
	}

	return nil
}
Beispiel #3
0
func validFieldType(fieldName string, target interface{}, fieldType string) bool {
	fieldKind, err := reflections.GetFieldKind(target, fieldName)

	if err != nil {
		return false
	}

	return fieldKind == fieldKindFromFieldType(fieldType)

}
Beispiel #4
0
func (l Loader) fieldValueIsEmpty(fieldName string) bool {
	// We need to use the field kind to determine the type of empty test.
	value, _ := reflections.GetField(l.Config, fieldName)
	fieldKind, _ := reflections.GetFieldKind(l.Config, fieldName)

	if fieldKind == reflect.String {
		return value == ""
	} else if fieldKind == reflect.Slice {
		v := reflect.ValueOf(value)
		return v.Len() == 0
	} else if fieldKind == reflect.Bool {
		return value == false
	} else {
		panic(fmt.Sprintf("Can't determine empty-ness for field type %s", fieldKind))
	}

	return false
}
Beispiel #5
0
// createFieldInfos creates the fieldInfos for a struct s.
// Only information from the struct (headerName, fieldName and kind) is available,
// all field positions are initialized with an invalid value of -1
func createFieldInfos(s interface{}) (fieldInfos, error) {
	if reflect.TypeOf(s).Kind() != reflect.Struct {
		return nil, ErrNoStruct
	}
	fieldInfos := []fieldInfo{}
	headerNameMap := map[string]interface{}{} // to detect duplicate csv tag names
	fieldNames, err := reflections.Fields(s)
	if err != nil {
		return nil, err
	}
	for _, fieldName := range fieldNames {
		headerName, err := reflections.GetFieldTag(s, fieldName, "csv")
		if err != nil {
			return nil, err
		}
		// csv fieldtags that contain a dash are ignored
		if strings.Contains(headerName, "-") {
			continue
		}
		if _, ok := headerNameMap[headerName]; ok {
			return nil, fmt.Errorf("duplicate csv tag name: %s", headerName)
		}
		headerNameMap[headerName] = nil
		kind, err := reflections.GetFieldKind(s, fieldName)
		if err != nil {
			return nil, err
		}
		if len(headerName) == 0 {
			return nil, fmt.Errorf("empty csv tag for field: %s", fieldName)
		}
		fieldInfos = append(fieldInfos, fieldInfo{
			headerName: headerName,
			fieldName:  fieldName,
			position:   -1,
			kind:       kind,
		})
	}
	return fieldInfos, nil
}
Beispiel #6
0
// SetField sets the value of the given field.
func (dc *DeepCopier) SetField(options *FieldOptions) error {
	if options.Skip {
		return nil
	}

	if dc.Reversed {
		has, _ := reflections.HasField(dc.Destination, options.SourceField)
		if !has {
			return nil
		}
	}

	has, _ := reflections.HasField(dc.Source, options.SourceField)
	if !has {
		err := dc.HandleMethod(options)
		if err != nil {
			has, _ = reflections.HasField(dc.Destination, options.DestinationField)
			if has {
				return nil
			}
		}
		return nil
	}

	kind, _ := reflections.GetFieldKind(dc.Source, options.SourceField)
	if kind == reflect.Struct {
		if err := dc.HandleStructField(options); err != nil {
			return err
		}
		return nil
	}

	if err := dc.HandleField(options); err != nil {
		return err
	}

	return nil
}
Beispiel #7
0
func (l Loader) normalizeField(fieldName string, normalization string) error {
	if normalization == "filepath" {
		value, _ := reflections.GetField(l.Config, fieldName)
		fieldKind, _ := reflections.GetFieldKind(l.Config, fieldName)

		// Make sure we're normalizing a string filed
		if fieldKind != reflect.String {
			return fmt.Errorf("filepath normalization only works on string fields")
		}

		// Normalize the field to be a filepath
		if valueAsString, ok := value.(string); ok {
			normalizedPath := NormalizeFilePath(valueAsString)
			if err := reflections.SetField(l.Config, fieldName, normalizedPath); err != nil {
				return err
			}
		}
	} else {
		return fmt.Errorf("Unknown normalization `%s`", normalization)
	}

	return nil
}
Beispiel #8
0
func formTagFromField(fieldName string, target interface{}) (string, error) {
	fieldKind, err := reflections.GetFieldKind(target, fieldName)
	f, _ := reflections.GetField(target, fieldName)
	fmt.Printf("Field %v\n", f)
	if err != nil {
		return "", err
	}

	choices, _ := reflections.GetFieldTag(target, fieldName, "choices")

	switch fieldKind {
	case reflect.String:
		if choices != "" {
			return "list", nil
		}
		return "input", nil
	case reflect.Slice:

		return "checkbox", nil
	case reflect.Bool:
		return "confirm", nil
	}
	return "", nil
}
// Reflects on the values in the commandLineOptions structure, and fills it
// with values either from the command line, or from the ENV.
func parseArgs(opts *commandLineOptions, args []string) {
	// Create a flag set for args
	flags := flag.NewFlagSet(commandLineName, flag.ExitOnError)

	// Get the fields for the strucutre
	fields, _ := reflections.Fields(opts)

	// Loop through each field of the structure, and define a flag for it
	for i := 0; i < len(fields); i++ {
		fieldName := fields[i]
		flagName, _ := reflections.GetFieldTag(opts, fieldName, "flag")
		fieldKind, _ := reflections.GetFieldKind(opts, fieldName)

		if fieldKind == reflect.String {
			flags.String(flagName, "", "")
		} else if fieldKind == reflect.Bool {
			flags.Bool(flagName, false, "")
		} else {
			exitAndError(fmt.Sprintf("Could not create flag for %s", fieldName))
		}
	}

	// Define our custom usage text
	flags.Usage = func() {
		fmt.Printf("%s\n", commandLineUsage)
	}

	// Search the args until we find a "--", which signifies the user has started
	// defining options.
	var argumentFlags []string
	started := false
	for i := 0; i < len(args); i++ {
		if strings.HasPrefix(args[i], "--") {
			started = true
		}

		if started {
			argumentFlags = append(argumentFlags, args[i])
		}
	}

	// Now parse the flags
	flags.Parse(argumentFlags)

	// Now the flag set has been populated with values, retrieve them and
	// set them (or use the ENV variable if empty)
	for i := 0; i < len(fields); i++ {
		fieldName := fields[i]
		fieldKind, _ := reflections.GetFieldKind(opts, fieldName)

		// Grab the flags we need
		flagName, _ := reflections.GetFieldTag(opts, fieldName, "flag")
		envName, _ := reflections.GetFieldTag(opts, fieldName, "env")
		required, _ := reflections.GetFieldTag(opts, fieldName, "required")

		// Grab the value from the flag
		value := flags.Lookup(flagName).Value.String()

		// If the value of the flag is empty, try the ENV
		if value == "" {
			value = os.Getenv(envName)
		}

		// Do validation
		if required == "true" && value == "" {
			exitAndError(fmt.Sprintf("missing %s", flagName))
		}

		// Set the value in the right way
		if fieldKind == reflect.String {
			reflections.SetField(opts, fieldName, value)
		} else if fieldKind == reflect.Bool {
			// The bool is converted to a string above
			if value == "true" {
				reflections.SetField(opts, fieldName, true)
			} else {
				reflections.SetField(opts, fieldName, false)
			}
		} else {
			exitAndError(fmt.Sprintf("Could not set value of %s", fieldName))
		}
	}
}
Beispiel #10
0
func (l Loader) setFieldValueFromCLI(fieldName string, cliName string) error {
	// Get the kind of field we need to set
	fieldKind, err := reflections.GetFieldKind(l.Config, fieldName)
	if err != nil {
		return fmt.Errorf(`Failed to get the type of struct field %s`, fieldName)
	}

	var value interface{}

	// See the if the cli option is using the special format i.e. (arg:1)
	special := CLISpecialNameRegex.FindStringSubmatch(cliName)
	if len(special) == 3 {
		// Should this cli option be loaded from the CLI arguments?
		if special[1] == "arg" {
			// Convert the arg position to an integer
			i, err := strconv.Atoi(special[2])
			if err != nil {
				return fmt.Errorf("Failed to convert string to int: %s", err)
			}

			// Only set the value if the args are long enough for
			// the position to exist.
			if len(l.CLI.Args()) > i {
				// Get the value from the args
				value = l.CLI.Args()[i]
			}
		}
	} else {
		// If the cli name didn't have the special format, then we need to
		// either load from the context's flags, or from a config file.

		// We start by defaulting the value to what ever was provided
		// by the configuration file
		if l.File != nil {
			if configFileValue, ok := l.File.Config[cliName]; ok {
				// Convert the config file value to it's correct type
				if fieldKind == reflect.String {
					value = configFileValue
				} else if fieldKind == reflect.Slice {
					value = strings.Split(configFileValue, ",")
				} else if fieldKind == reflect.Bool {
					value, _ = strconv.ParseBool(configFileValue)
				} else {
					return fmt.Errorf("Unable to convert string to type %s", fieldKind)
				}
			}
		}

		// If a value hasn't been found in a config file, but there
		// _is_ one provided by the CLI context, then use that.
		if value == nil || l.cliValueIsSet(cliName) {
			if fieldKind == reflect.String {
				value = l.CLI.String(cliName)
			} else if fieldKind == reflect.Slice {
				value = l.CLI.StringSlice(cliName)
			} else if fieldKind == reflect.Bool {
				value = l.CLI.Bool(cliName)
			} else {
				return fmt.Errorf("Unable to handle type: %s", fieldKind)
			}
		}
	}

	// Set the value to the cfg
	if value != nil {
		err = reflections.SetField(l.Config, fieldName, value)
		if err != nil {
			return fmt.Errorf("Could not set value `%s` to field `%s` (%s)", value, fieldName, err)
		}
	}

	return nil
}