summaryrefslogtreecommitdiff
path: root/vendor/github.com/gocarina/gocsv/types.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/gocarina/gocsv/types.go')
-rw-r--r--vendor/github.com/gocarina/gocsv/types.go456
1 files changed, 456 insertions, 0 deletions
diff --git a/vendor/github.com/gocarina/gocsv/types.go b/vendor/github.com/gocarina/gocsv/types.go
new file mode 100644
index 0000000..50d88ce
--- /dev/null
+++ b/vendor/github.com/gocarina/gocsv/types.go
@@ -0,0 +1,456 @@
+package gocsv
+
+import (
+ "encoding"
+ "fmt"
+ "reflect"
+ "strconv"
+ "strings"
+)
+
+// --------------------------------------------------------------------------
+// Conversion interfaces
+
+// TypeMarshaller is implemented by any value that has a MarshalCSV method
+// This converter is used to convert the value to it string representation
+type TypeMarshaller interface {
+ MarshalCSV() (string, error)
+}
+
+// Stringer is implemented by any value that has a String method
+// This converter is used to convert the value to it string representation
+// This converter will be used if your value does not implement TypeMarshaller
+type Stringer interface {
+ String() string
+}
+
+// TypeUnmarshaller is implemented by any value that has an UnmarshalCSV method
+// This converter is used to convert a string to your value representation of that string
+type TypeUnmarshaller interface {
+ UnmarshalCSV(string) error
+}
+
+// NoUnmarshalFuncError is the custom error type to be raised in case there is no unmarshal function defined on type
+type NoUnmarshalFuncError struct {
+ msg string
+}
+
+func (e NoUnmarshalFuncError) Error() string {
+ return e.msg
+}
+
+// NoMarshalFuncError is the custom error type to be raised in case there is no marshal function defined on type
+type NoMarshalFuncError struct {
+ msg string
+}
+
+func (e NoMarshalFuncError) Error() string {
+ return e.msg
+}
+
+var (
+ stringerType = reflect.TypeOf((*Stringer)(nil)).Elem()
+ marshallerType = reflect.TypeOf((*TypeMarshaller)(nil)).Elem()
+ unMarshallerType = reflect.TypeOf((*TypeUnmarshaller)(nil)).Elem()
+ textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
+ textUnMarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
+)
+
+// --------------------------------------------------------------------------
+// Conversion helpers
+
+func toString(in interface{}) (string, error) {
+ inValue := reflect.ValueOf(in)
+
+ switch inValue.Kind() {
+ case reflect.String:
+ return inValue.String(), nil
+ case reflect.Bool:
+ b := inValue.Bool()
+ if b {
+ return "true", nil
+ }
+ return "false", nil
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return fmt.Sprintf("%v", inValue.Int()), nil
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ return fmt.Sprintf("%v", inValue.Uint()), nil
+ case reflect.Float32:
+ return strconv.FormatFloat(inValue.Float(), byte('f'), -1, 32), nil
+ case reflect.Float64:
+ return strconv.FormatFloat(inValue.Float(), byte('f'), -1, 64), nil
+ }
+ return "", fmt.Errorf("No known conversion from " + inValue.Type().String() + " to string")
+}
+
+func toBool(in interface{}) (bool, error) {
+ inValue := reflect.ValueOf(in)
+
+ switch inValue.Kind() {
+ case reflect.String:
+ s := inValue.String()
+ switch s {
+ case "yes":
+ return true, nil
+ case "no", "":
+ return false, nil
+ default:
+ return strconv.ParseBool(s)
+ }
+ case reflect.Bool:
+ return inValue.Bool(), nil
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ i := inValue.Int()
+ if i != 0 {
+ return true, nil
+ }
+ return false, nil
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ i := inValue.Uint()
+ if i != 0 {
+ return true, nil
+ }
+ return false, nil
+ case reflect.Float32, reflect.Float64:
+ f := inValue.Float()
+ if f != 0 {
+ return true, nil
+ }
+ return false, nil
+ }
+ return false, fmt.Errorf("No known conversion from " + inValue.Type().String() + " to bool")
+}
+
+func toInt(in interface{}) (int64, error) {
+ inValue := reflect.ValueOf(in)
+
+ switch inValue.Kind() {
+ case reflect.String:
+ s := strings.TrimSpace(inValue.String())
+ if s == "" {
+ return 0, nil
+ }
+ return strconv.ParseInt(s, 0, 64)
+ case reflect.Bool:
+ if inValue.Bool() {
+ return 1, nil
+ }
+ return 0, nil
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return inValue.Int(), nil
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ return int64(inValue.Uint()), nil
+ case reflect.Float32, reflect.Float64:
+ return int64(inValue.Float()), nil
+ }
+ return 0, fmt.Errorf("No known conversion from " + inValue.Type().String() + " to int")
+}
+
+func toUint(in interface{}) (uint64, error) {
+ inValue := reflect.ValueOf(in)
+
+ switch inValue.Kind() {
+ case reflect.String:
+ s := strings.TrimSpace(inValue.String())
+ if s == "" {
+ return 0, nil
+ }
+
+ // support the float input
+ if strings.Contains(s, ".") {
+ f, err := strconv.ParseFloat(s, 64)
+ if err != nil {
+ return 0, err
+ }
+ return uint64(f), nil
+ }
+ return strconv.ParseUint(s, 0, 64)
+ case reflect.Bool:
+ if inValue.Bool() {
+ return 1, nil
+ }
+ return 0, nil
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return uint64(inValue.Int()), nil
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ return inValue.Uint(), nil
+ case reflect.Float32, reflect.Float64:
+ return uint64(inValue.Float()), nil
+ }
+ return 0, fmt.Errorf("No known conversion from " + inValue.Type().String() + " to uint")
+}
+
+func toFloat(in interface{}) (float64, error) {
+ inValue := reflect.ValueOf(in)
+
+ switch inValue.Kind() {
+ case reflect.String:
+ s := strings.TrimSpace(inValue.String())
+ if s == "" {
+ return 0, nil
+ }
+ return strconv.ParseFloat(s, 64)
+ case reflect.Bool:
+ if inValue.Bool() {
+ return 1, nil
+ }
+ return 0, nil
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return float64(inValue.Int()), nil
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ return float64(inValue.Uint()), nil
+ case reflect.Float32, reflect.Float64:
+ return inValue.Float(), nil
+ }
+ return 0, fmt.Errorf("No known conversion from " + inValue.Type().String() + " to float")
+}
+
+func setField(field reflect.Value, value string, omitEmpty bool) error {
+ if field.Kind() == reflect.Ptr {
+ if omitEmpty && value == "" {
+ return nil
+ }
+ if field.IsNil() {
+ field.Set(reflect.New(field.Type().Elem()))
+ }
+ field = field.Elem()
+ }
+
+ switch field.Interface().(type) {
+ case string:
+ s, err := toString(value)
+ if err != nil {
+ return err
+ }
+ field.SetString(s)
+ case bool:
+ b, err := toBool(value)
+ if err != nil {
+ return err
+ }
+ field.SetBool(b)
+ case int, int8, int16, int32, int64:
+ i, err := toInt(value)
+ if err != nil {
+ return err
+ }
+ field.SetInt(i)
+ case uint, uint8, uint16, uint32, uint64:
+ ui, err := toUint(value)
+ if err != nil {
+ return err
+ }
+ field.SetUint(ui)
+ case float32, float64:
+ f, err := toFloat(value)
+ if err != nil {
+ return err
+ }
+ field.SetFloat(f)
+ default:
+ // Not a native type, check for unmarshal method
+ if err := unmarshall(field, value); err != nil {
+ if _, ok := err.(NoUnmarshalFuncError); !ok {
+ return err
+ }
+ // Could not unmarshal, check for kind, e.g. renamed type from basic type
+ switch field.Kind() {
+ case reflect.String:
+ s, err := toString(value)
+ if err != nil {
+ return err
+ }
+ field.SetString(s)
+ case reflect.Bool:
+ b, err := toBool(value)
+ if err != nil {
+ return err
+ }
+ field.SetBool(b)
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ i, err := toInt(value)
+ if err != nil {
+ return err
+ }
+ field.SetInt(i)
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ ui, err := toUint(value)
+ if err != nil {
+ return err
+ }
+ field.SetUint(ui)
+ case reflect.Float32, reflect.Float64:
+ f, err := toFloat(value)
+ if err != nil {
+ return err
+ }
+ field.SetFloat(f)
+ default:
+ return err
+ }
+ } else {
+ return nil
+ }
+ }
+ return nil
+}
+
+func getFieldAsString(field reflect.Value) (str string, err error) {
+ switch field.Kind() {
+ case reflect.Interface:
+ case reflect.Ptr:
+ if field.IsNil() {
+ return "", nil
+ }
+ return getFieldAsString(field.Elem())
+ default:
+ // Check if field is go native type
+ switch field.Interface().(type) {
+ case string:
+ return field.String(), nil
+ case bool:
+ str, err = toString(field.Bool())
+ if err != nil {
+ return str, err
+ }
+ case int, int8, int16, int32, int64:
+ str, err = toString(field.Int())
+ if err != nil {
+ return str, err
+ }
+ case uint, uint8, uint16, uint32, uint64:
+ str, err = toString(field.Uint())
+ if err != nil {
+ return str, err
+ }
+ case float32:
+ str, err = toString(float32(field.Float()))
+ if err != nil {
+ return str, err
+ }
+ case float64:
+ str, err = toString(field.Float())
+ if err != nil {
+ return str, err
+ }
+ default:
+ // Not a native type, check for marshal method
+ str, err = marshall(field)
+ if err != nil {
+ if _, ok := err.(NoMarshalFuncError); !ok {
+ return str, err
+ }
+ // If not marshal method, is field compatible with/renamed from native type
+ switch field.Kind() {
+ case reflect.String:
+ return field.String(), nil
+ case reflect.Bool:
+ str, err = toString(field.Bool())
+ if err != nil {
+ return str, err
+ }
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ str, err = toString(field.Int())
+ if err != nil {
+ return str, err
+ }
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ str, err = toString(field.Uint())
+ if err != nil {
+ return str, err
+ }
+ case reflect.Float32:
+ str, err = toString(float32(field.Float()))
+ if err != nil {
+ return str, err
+ }
+ case reflect.Float64:
+ str, err = toString(field.Float())
+ if err != nil {
+ return str, err
+ }
+ }
+ } else {
+ return str, nil
+ }
+ }
+ }
+ return str, nil
+}
+
+// --------------------------------------------------------------------------
+// Un/serializations helpers
+
+func unmarshall(field reflect.Value, value string) error {
+ dupField := field
+ unMarshallIt := func(finalField reflect.Value) error {
+ if finalField.CanInterface() {
+ fieldIface := finalField.Interface()
+
+ fieldTypeUnmarshaller, ok := fieldIface.(TypeUnmarshaller)
+ if ok {
+ return fieldTypeUnmarshaller.UnmarshalCSV(value)
+ }
+
+ // Otherwise try to use TextUnmarshaler
+ fieldTextUnmarshaler, ok := fieldIface.(encoding.TextUnmarshaler)
+ if ok {
+ return fieldTextUnmarshaler.UnmarshalText([]byte(value))
+ }
+ }
+
+ return NoUnmarshalFuncError{"No known conversion from string to " + field.Type().String() + ", " + field.Type().String() + " does not implement TypeUnmarshaller"}
+ }
+ for dupField.Kind() == reflect.Interface || dupField.Kind() == reflect.Ptr {
+ if dupField.IsNil() {
+ dupField = reflect.New(field.Type().Elem())
+ field.Set(dupField)
+ return unMarshallIt(dupField)
+ }
+ dupField = dupField.Elem()
+ }
+ if dupField.CanAddr() {
+ return unMarshallIt(dupField.Addr())
+ }
+ return NoUnmarshalFuncError{"No known conversion from string to " + field.Type().String() + ", " + field.Type().String() + " does not implement TypeUnmarshaller"}
+}
+
+func marshall(field reflect.Value) (value string, err error) {
+ dupField := field
+ marshallIt := func(finalField reflect.Value) (string, error) {
+ if finalField.CanInterface() {
+ fieldIface := finalField.Interface()
+
+ // Use TypeMarshaller when possible
+ fieldTypeMarhaller, ok := fieldIface.(TypeMarshaller)
+ if ok {
+ return fieldTypeMarhaller.MarshalCSV()
+ }
+
+ // Otherwise try to use TextMarshaller
+ fieldTextMarshaler, ok := fieldIface.(encoding.TextMarshaler)
+ if ok {
+ text, err := fieldTextMarshaler.MarshalText()
+ return string(text), err
+ }
+
+ // Otherwise try to use Stringer
+ fieldStringer, ok := fieldIface.(Stringer)
+ if ok {
+ return fieldStringer.String(), nil
+ }
+ }
+
+ return value, NoMarshalFuncError{"No known conversion from " + field.Type().String() + " to string, " + field.Type().String() + " does not implement TypeMarshaller nor Stringer"}
+ }
+ for dupField.Kind() == reflect.Interface || dupField.Kind() == reflect.Ptr {
+ if dupField.IsNil() {
+ return value, nil
+ }
+ dupField = dupField.Elem()
+ }
+ if dupField.CanAddr() {
+ return marshallIt(dupField.Addr())
+ }
+ return value, NoMarshalFuncError{"No known conversion from " + field.Type().String() + " to string, " + field.Type().String() + " does not implement TypeMarshaller nor Stringer"}
+}