@@ -182,8 +182,26 @@ func NewFromString(value string) (Decimal, error) {
182
182
var intString string
183
183
var exp int64
184
184
185
- // Check if number is using scientific notation
186
- eIndex := strings .IndexAny (value , "Ee" )
185
+ // Check if number is using scientific notation and find dots
186
+ eIndex := - 1
187
+ pIndex := - 1
188
+ for i , r := range value {
189
+ if r == 'E' || r == 'e' {
190
+ if eIndex > - 1 {
191
+ return Decimal {}, fmt .Errorf ("can't convert %s to decimal: multiple 'E' characters found" , value )
192
+ }
193
+ eIndex = i
194
+ continue
195
+ }
196
+
197
+ if r == '.' {
198
+ if pIndex > - 1 {
199
+ return Decimal {}, fmt .Errorf ("can't convert %s to decimal: too many .s" , value )
200
+ }
201
+ pIndex = i
202
+ }
203
+ }
204
+
187
205
if eIndex != - 1 {
188
206
expInt , err := strconv .ParseInt (value [eIndex + 1 :], 10 , 32 )
189
207
if err != nil {
@@ -196,23 +214,12 @@ func NewFromString(value string) (Decimal, error) {
196
214
exp = expInt
197
215
}
198
216
199
- pIndex := - 1
200
- vLen := len (value )
201
- for i := 0 ; i < vLen ; i ++ {
202
- if value [i ] == '.' {
203
- if pIndex > - 1 {
204
- return Decimal {}, fmt .Errorf ("can't convert %s to decimal: too many .s" , value )
205
- }
206
- pIndex = i
207
- }
208
- }
209
-
210
217
if pIndex == - 1 {
211
218
// There is no decimal point, we can just parse the original string as
212
219
// an int
213
220
intString = value
214
221
} else {
215
- if pIndex + 1 < vLen {
222
+ if pIndex + 1 < len ( value ) {
216
223
intString = value [:pIndex ] + value [pIndex + 1 :]
217
224
} else {
218
225
intString = value [:pIndex ]
@@ -1766,15 +1773,10 @@ func (d *Decimal) UnmarshalJSON(decimalBytes []byte) error {
1766
1773
return nil
1767
1774
}
1768
1775
1769
- str , err := unquoteIfQuoted (decimalBytes )
1770
- if err != nil {
1771
- return fmt .Errorf ("error decoding string '%s': %s" , decimalBytes , err )
1772
- }
1773
-
1774
- decimal , err := NewFromString (str )
1776
+ decimal , err := NewFromString (unquoteIfQuoted (string (decimalBytes )))
1775
1777
* d = decimal
1776
1778
if err != nil {
1777
- return fmt .Errorf ("error decoding string '%s': %s" , str , err )
1779
+ return fmt .Errorf ("error decoding string '%s': %s" , string ( decimalBytes ) , err )
1778
1780
}
1779
1781
return nil
1780
1782
}
@@ -1852,14 +1854,18 @@ func (d *Decimal) Scan(value interface{}) error {
1852
1854
* d = NewFromUint64 (v )
1853
1855
return nil
1854
1856
1855
- default :
1856
- // default is trying to interpret value stored as string
1857
- str , err := unquoteIfQuoted (v )
1858
- if err != nil {
1859
- return err
1860
- }
1861
- * d , err = NewFromString (str )
1857
+ case string :
1858
+ var err error
1859
+ * d , err = NewFromString (unquoteIfQuoted (v ))
1860
+ return err
1861
+
1862
+ case []byte :
1863
+ var err error
1864
+ * d , err = NewFromString (unquoteIfQuoted (string (v )))
1862
1865
return err
1866
+
1867
+ default :
1868
+ return fmt .Errorf ("could not convert value '%+v' to any known type" , value )
1863
1869
}
1864
1870
}
1865
1871
@@ -2021,23 +2027,13 @@ func RescalePair(d1 Decimal, d2 Decimal) (Decimal, Decimal) {
2021
2027
return d1 , d2
2022
2028
}
2023
2029
2024
- func unquoteIfQuoted (value interface {}) (string , error ) {
2025
- var bytes []byte
2026
-
2027
- switch v := value .(type ) {
2028
- case string :
2029
- bytes = []byte (v )
2030
- case []byte :
2031
- bytes = v
2032
- default :
2033
- return "" , fmt .Errorf ("could not convert value '%+v' to byte array of type '%T'" , value , value )
2034
- }
2035
-
2030
+ func unquoteIfQuoted (value string ) string {
2036
2031
// If the amount is quoted, strip the quotes
2037
- if len (bytes ) > 2 && bytes [0 ] == '"' && bytes [len (bytes )- 1 ] == '"' {
2038
- bytes = bytes [1 : len (bytes )- 1 ]
2032
+ if len (value ) > 2 && value [0 ] == '"' && value [len (value )- 1 ] == '"' {
2033
+ return value [1 : len (value )- 1 ]
2039
2034
}
2040
- return string (bytes ), nil
2035
+
2036
+ return value
2041
2037
}
2042
2038
2043
2039
// NullDecimal represents a nullable decimal with compatibility for
0 commit comments