comma.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. package parser
  2. import (
  3. "bytes"
  4. "fmt"
  5. "reflect"
  6. "strconv"
  7. )
  8. // ParserCommaSeparatedValues parses the comma separated values
  9. // and returns a map of key-value pairs
  10. // examples:
  11. // data: a=1,b=2
  12. //
  13. // T: type struct {
  14. // A int `comma:"a"`
  15. // B string `comma:"b"`
  16. // }
  17. //
  18. // return:
  19. // T{A: 1, B: "2"}
  20. func ParserCommaSeparatedValues[T any](data []byte) (T, error) {
  21. var result T
  22. if len(data) == 0 {
  23. return result, nil
  24. }
  25. // Split by comma
  26. pairs := bytes.Split(data, []byte(","))
  27. // Create map to store key-value pairs
  28. values := make(map[string]string)
  29. // Parse each key-value pair
  30. for _, pair := range pairs {
  31. kv := bytes.Split(pair, []byte("="))
  32. if len(kv) != 2 {
  33. return result, fmt.Errorf("invalid key-value pair: %s", pair)
  34. }
  35. key := string(bytes.TrimSpace(kv[0]))
  36. value := string(bytes.TrimSpace(kv[1]))
  37. values[key] = value
  38. }
  39. // Convert map to struct using reflection
  40. resultValue := reflect.ValueOf(&result).Elem()
  41. resultType := resultValue.Type()
  42. for i := 0; i < resultType.NumField(); i++ {
  43. field := resultType.Field(i)
  44. fieldValue := resultValue.Field(i)
  45. // Get comma tag value
  46. tag := field.Tag.Get("comma")
  47. if tag == "" {
  48. tag = field.Name
  49. }
  50. if value, ok := values[tag]; ok {
  51. switch field.Type.Kind() {
  52. case reflect.String:
  53. fieldValue.SetString(value)
  54. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  55. if intVal, err := strconv.ParseInt(value, 10, 64); err == nil {
  56. fieldValue.SetInt(intVal)
  57. }
  58. case reflect.Float32, reflect.Float64:
  59. if floatVal, err := strconv.ParseFloat(value, 64); err == nil {
  60. fieldValue.SetFloat(floatVal)
  61. }
  62. case reflect.Bool:
  63. if boolVal, err := strconv.ParseBool(value); err == nil {
  64. fieldValue.SetBool(boolVal)
  65. }
  66. }
  67. }
  68. }
  69. return result, nil
  70. }