@@ -182,8 +182,23 @@ func NewFromString(value string) (Decimal, error) {
182182 var intString string
183183 var exp int64
184184
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 eIndex == - 1 && (r == 'E' || r == 'e' ) {
190+ eIndex = i
191+ continue
192+ }
193+
194+ if r == '.' {
195+ if pIndex > - 1 {
196+ return Decimal {}, fmt .Errorf ("can't convert %s to decimal: too many .s" , value )
197+ }
198+ pIndex = i
199+ }
200+ }
201+
187202 if eIndex != - 1 {
188203 expInt , err := strconv .ParseInt (value [eIndex + 1 :], 10 , 32 )
189204 if err != nil {
@@ -196,23 +211,12 @@ func NewFromString(value string) (Decimal, error) {
196211 exp = expInt
197212 }
198213
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-
210214 if pIndex == - 1 {
211215 // There is no decimal point, we can just parse the original string as
212216 // an int
213217 intString = value
214218 } else {
215- if pIndex + 1 < vLen {
219+ if pIndex + 1 < len ( value ) {
216220 intString = value [:pIndex ] + value [pIndex + 1 :]
217221 } else {
218222 intString = value [:pIndex ]
@@ -1766,15 +1770,10 @@ func (d *Decimal) UnmarshalJSON(decimalBytes []byte) error {
17661770 return nil
17671771 }
17681772
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 )
1773+ decimal , err := NewFromString (unquoteIfQuoted (string (decimalBytes )))
17751774 * d = decimal
17761775 if err != nil {
1777- return fmt .Errorf ("error decoding string '%s': %s" , str , err )
1776+ return fmt .Errorf ("error decoding string '%s': %s" , string ( decimalBytes ) , err )
17781777 }
17791778 return nil
17801779}
@@ -1852,14 +1851,18 @@ func (d *Decimal) Scan(value interface{}) error {
18521851 * d = NewFromUint64 (v )
18531852 return nil
18541853
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 )
1854+ case string :
1855+ var err error
1856+ * d , err = NewFromString (unquoteIfQuoted (v ))
18621857 return err
1858+
1859+ case []byte :
1860+ var err error
1861+ * d , err = NewFromString (unquoteIfQuoted (string (v )))
1862+ return err
1863+
1864+ default :
1865+ return fmt .Errorf ("could not convert value '%+v' to any known type" , value )
18631866 }
18641867}
18651868
@@ -2021,23 +2024,13 @@ func RescalePair(d1 Decimal, d2 Decimal) (Decimal, Decimal) {
20212024 return d1 , d2
20222025}
20232026
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-
2027+ func unquoteIfQuoted (value string ) string {
20362028 // 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 ]
2029+ if len (value ) > 2 && value [0 ] == '"' && value [len (value )- 1 ] == '"' {
2030+ return value [1 : len (value )- 1 ]
20392031 }
2040- return string (bytes ), nil
2032+
2033+ return value
20412034}
20422035
20432036// NullDecimal represents a nullable decimal with compatibility for
0 commit comments