@@ -19,13 +19,55 @@ import (
1919// // Handle error
2020// }
2121func ParseValue [T ParsableType ](value string ) (T , yaerrors.Error ) {
22+ return ParseValueWithCustomType [T ](value , reflect .TypeOf (new (T )).Elem ())
23+ }
24+
25+ // ParseValueWithCustomType is a generic function that converts a string value to the specified type T,
26+ // using the provided valueType for conversion. It returns the converted value and an error if the conversion fails.
27+ // This function is useful when you need to specify a custom type for parsing, such as when using a custom unmarshal.
28+ //
29+ // Example usage:
30+ //
31+ // type YourCustomType uint64
32+ //
33+ // func (s *YourCustomType) Unmarshal(data string) error {
34+ // if s == nil {
35+ // return fmt.Errorf("nil pointer to YourCustomType")
36+ // }
37+ //
38+ // switch data {
39+ // case "FIRST":
40+ // *s = 1
41+ // case "SECOND":
42+ // *s = 2
43+ // default:
44+ // return fmt.Errorf("unknown value: %s", data)
45+ // }
46+ //
47+ // return nil
48+ // }
49+ //
50+ // customValue, err := ParseValueWithCustomType[uint64]("FIRST", reflect.TypeOf(YourCustomType(0)))
51+ //
52+ // if err != nil {
53+ // // Handle error
54+ // }
55+ func ParseValueWithCustomType [T ParsableType ](
56+ value string ,
57+ valueType reflect.Type ,
58+ ) (T , yaerrors.Error ) {
2259 var zero T
2360
24- typ := reflect .TypeOf (zero )
61+ zeroType := reflect .TypeOf (zero )
2562
26- switch typ .Kind () {
63+ switch valueType .Kind () {
2764 case reflect .String :
2865 if val , ok := any (value ).(T ); ok {
66+ unmarshaled , err := TryUnmarshal [T ](value , valueType )
67+ if err == nil {
68+ return unmarshaled , nil
69+ }
70+
2971 return val , nil
3072 }
3173
@@ -37,34 +79,39 @@ func ParseValue[T ParsableType](value string) (T, yaerrors.Error) {
3779
3880 case reflect .Int , reflect .Int8 , reflect .Int16 , reflect .Int32 , reflect .Int64 :
3981 if intValue , err := strconv .ParseInt (value , 10 , 64 ); err == nil {
40- if val , ok := reflect .ValueOf (intValue ).Convert (typ ).Interface ().(T ); ok {
82+ if val , ok := reflect .ValueOf (intValue ).Convert (zeroType ).Interface ().(T ); ok {
4183 return val , nil
4284 }
4385 }
4486
45- case reflect .Uint , reflect .Uint8 , reflect .Uint16 , reflect .Uint32 , reflect .Uint64 :
87+ case reflect .Uint ,
88+ reflect .Uint8 ,
89+ reflect .Uint16 ,
90+ reflect .Uint32 ,
91+ reflect .Uint64 ,
92+ reflect .Uintptr :
4693 if uintValue , err := strconv .ParseUint (value , 10 , 64 ); err == nil {
47- if val , ok := reflect .ValueOf (uintValue ).Convert (typ ).Interface ().(T ); ok {
94+ if val , ok := reflect .ValueOf (uintValue ).Convert (zeroType ).Interface ().(T ); ok {
4895 return val , nil
4996 }
5097 }
5198
5299 case reflect .Float32 , reflect .Float64 :
53100 if floatValue , err := strconv .ParseFloat (value , 64 ); err == nil {
54- if val , ok := reflect .ValueOf (floatValue ).Convert (typ ).Interface ().(T ); ok {
101+ if val , ok := reflect .ValueOf (floatValue ).Convert (zeroType ).Interface ().(T ); ok {
55102 return val , nil
56103 }
57104 }
58105
59106 case reflect .Bool :
60107 if boolValue , err := strconv .ParseBool (value ); err == nil {
61- if val , ok := reflect .ValueOf (boolValue ).Convert (typ ).Interface ().(T ); ok {
108+ if val , ok := reflect .ValueOf (boolValue ).Convert (zeroType ).Interface ().(T ); ok {
62109 return val , nil
63110 }
64111 }
65112
66113 case reflect .Slice :
67- if typ .Elem ().Kind () == reflect .Uint8 {
114+ if valueType .Elem ().Kind () == reflect .Uint8 {
68115 if val , ok := any ([]byte (value )).(T ); ok {
69116 return val , nil
70117 }
@@ -77,21 +124,20 @@ func ParseValue[T ParsableType](value string) (T, yaerrors.Error) {
77124 reflect .Map ,
78125 reflect .Ptr ,
79126 reflect .Struct ,
80- reflect .Uintptr ,
81127 reflect .Complex64 ,
82128 reflect .Complex128 ,
83129 reflect .Array ,
84130 reflect .UnsafePointer :
85131 return zero , yaerrors .FromError (
86132 http .StatusInternalServerError ,
87133 ErrInvalidValue ,
88- "parse value: unsupported type " + typ .String (),
134+ "parse value: unsupported type " + valueType .String (),
89135 )
90136 }
91137
92- val , err := TryUnmarshal [T ](value , typ )
138+ val , err := TryUnmarshal [T ](value , valueType )
93139 if err != nil {
94- return zero , err
140+ return zero , err . Wrap ( "parse value: failed to unmarshal" )
95141 }
96142
97143 return val , nil
0 commit comments