1
1
//! Module for parsing an `IntermediateDecimal` into a `Decimal75`.
2
2
use crate :: {
3
- base:: scalar:: Scalar ,
4
- sql:: parse:: { ConversionError , ConversionResult } ,
3
+ base:: {
4
+ math:: decimal:: DecimalError :: {
5
+ IntermediateDecimalConversionError , InvalidPrecision , RoundingError ,
6
+ } ,
7
+ scalar:: Scalar ,
8
+ } ,
9
+ sql:: parse:: {
10
+ ConversionError :: { self , DecimalConversionError } ,
11
+ ConversionResult ,
12
+ } ,
5
13
} ;
6
- use proof_of_sql_parser:: intermediate_decimal:: IntermediateDecimal ;
14
+ use proof_of_sql_parser:: intermediate_decimal:: { IntermediateDecimal , IntermediateDecimalError } ;
7
15
use serde:: { Deserialize , Deserializer , Serialize } ;
16
+ use thiserror:: Error ;
17
+
18
+ /// Errors related to decimal operations.
19
+ #[ derive( Error , Debug , Eq , PartialEq ) ]
20
+ pub enum DecimalError {
21
+ #[ error( "Invalid decimal format or value: {0}" ) ]
22
+ /// Error when a decimal format or value is incorrect,
23
+ /// the string isn't even a decimal e.g. "notastring",
24
+ /// "-21.233.122" etc aka InvalidDecimal
25
+ InvalidDecimal ( String ) ,
26
+
27
+ #[ error( "Decimal precision is not valid: {0}" ) ]
28
+ /// Decimal precision exceeds the allowed limit,
29
+ /// e.g. precision above 75/76/whatever set by Scalar
30
+ /// or non-positive aka InvalidPrecision
31
+ InvalidPrecision ( String ) ,
32
+
33
+ #[ error( "Unsupported operation: cannot round decimal: {0}" ) ]
34
+ /// This error occurs when attempting to scale a
35
+ /// decimal in such a way that a loss of precision occurs.
36
+ RoundingError ( String ) ,
37
+
38
+ /// Errors that may occur when parsing an intermediate decimal
39
+ /// into a posql decimal
40
+ #[ error( "Intermediate decimal conversion error: {0}" ) ]
41
+ IntermediateDecimalConversionError ( IntermediateDecimalError ) ,
42
+ }
43
+
44
+ impl From < IntermediateDecimalError > for ConversionError {
45
+ fn from ( err : IntermediateDecimalError ) -> ConversionError {
46
+ DecimalConversionError ( IntermediateDecimalConversionError ( err) )
47
+ }
48
+ }
8
49
9
50
#[ derive( Eq , PartialEq , Debug , Clone , Hash , Serialize , Copy ) ]
10
51
/// limit-enforced precision
@@ -15,10 +56,10 @@ impl Precision {
15
56
/// Constructor for creating a Precision instance
16
57
pub fn new ( value : u8 ) -> Result < Self , ConversionError > {
17
58
if value > MAX_SUPPORTED_PRECISION || value == 0 {
18
- Err ( ConversionError :: PrecisionParseError ( format ! (
59
+ Err ( DecimalConversionError ( InvalidPrecision ( format ! (
19
60
"Failed to parse precision. Value of {} exceeds max supported precision of {}" ,
20
61
value, MAX_SUPPORTED_PRECISION
21
- ) ) )
62
+ ) ) ) )
22
63
} else {
23
64
Ok ( Precision ( value) )
24
65
}
@@ -73,9 +114,9 @@ impl<S: Scalar> Decimal<S> {
73
114
) -> ConversionResult < Decimal < S > > {
74
115
let scale_factor = new_scale - self . scale ;
75
116
if scale_factor < 0 || new_precision. value ( ) < self . precision . value ( ) + scale_factor as u8 {
76
- return Err ( ConversionError :: DecimalRoundingError (
117
+ return Err ( DecimalConversionError ( RoundingError (
77
118
"Scale factor must be non-negative" . to_string ( ) ,
78
- ) ) ;
119
+ ) ) ) ;
79
120
}
80
121
let scaled_value = scale_scalar ( self . value , scale_factor) ?;
81
122
Ok ( Decimal :: new ( scaled_value, new_precision, new_scale) )
@@ -86,14 +127,14 @@ impl<S: Scalar> Decimal<S> {
86
127
const MINIMAL_PRECISION : u8 = 19 ;
87
128
let raw_precision = precision. value ( ) ;
88
129
if raw_precision < MINIMAL_PRECISION {
89
- return Err ( ConversionError :: DecimalRoundingError (
130
+ return Err ( DecimalConversionError ( RoundingError (
90
131
"Precision must be at least 19" . to_string ( ) ,
91
- ) ) ;
132
+ ) ) ) ;
92
133
}
93
134
if scale < 0 || raw_precision < MINIMAL_PRECISION + scale as u8 {
94
- return Err ( ConversionError :: DecimalRoundingError (
135
+ return Err ( DecimalConversionError ( RoundingError (
95
136
"Can not scale down a decimal" . to_string ( ) ,
96
- ) ) ;
137
+ ) ) ) ;
97
138
}
98
139
let scaled_value = scale_scalar ( S :: from ( & value) , scale) ?;
99
140
Ok ( Decimal :: new ( scaled_value, precision, scale) )
@@ -104,14 +145,14 @@ impl<S: Scalar> Decimal<S> {
104
145
const MINIMAL_PRECISION : u8 = 39 ;
105
146
let raw_precision = precision. value ( ) ;
106
147
if raw_precision < MINIMAL_PRECISION {
107
- return Err ( ConversionError :: DecimalRoundingError (
148
+ return Err ( DecimalConversionError ( RoundingError (
108
149
"Precision must be at least 19" . to_string ( ) ,
109
- ) ) ;
150
+ ) ) ) ;
110
151
}
111
152
if scale < 0 || raw_precision < MINIMAL_PRECISION + scale as u8 {
112
- return Err ( ConversionError :: DecimalRoundingError (
153
+ return Err ( DecimalConversionError ( RoundingError (
113
154
"Can not scale down a decimal" . to_string ( ) ,
114
- ) ) ;
155
+ ) ) ) ;
115
156
}
116
157
let scaled_value = scale_scalar ( S :: from ( & value) , scale) ?;
117
158
Ok ( Decimal :: new ( scaled_value, precision, scale) )
@@ -132,8 +173,9 @@ impl<S: Scalar> Decimal<S> {
132
173
/// * `target_scale` - The scale (number of decimal places) to use in the scalar.
133
174
///
134
175
/// ## Errors
135
- /// Returns `ConversionError::PrecisionParseError` if the number of digits in
136
- /// the decimal exceeds the `target_precision` after adjusting for `target_scale`.
176
+ /// Returns `InvalidPrecision` error if the number of digits in
177
+ /// the decimal exceeds the `target_precision` before or after adjusting for
178
+ /// `target_scale`, or if the target precision is zero.
137
179
pub ( crate ) fn try_into_to_scalar < S : Scalar > (
138
180
d : & IntermediateDecimal ,
139
181
target_precision : Precision ,
@@ -147,9 +189,9 @@ pub(crate) fn try_into_to_scalar<S: Scalar>(
147
189
/// Note that we do not check for overflow.
148
190
pub ( crate ) fn scale_scalar < S : Scalar > ( s : S , scale : i8 ) -> ConversionResult < S > {
149
191
if scale < 0 {
150
- return Err ( ConversionError :: DecimalRoundingError (
192
+ return Err ( DecimalConversionError ( RoundingError (
151
193
"Scale factor must be non-negative" . to_string ( ) ,
152
- ) ) ;
194
+ ) ) ) ;
153
195
}
154
196
let ten = S :: from ( 10 ) ;
155
197
let mut res = s;
0 commit comments