Skip to content

Commit 6a393e4

Browse files
chore: Refactor decimal validation to the decimal module
1 parent af0766c commit 6a393e4

File tree

2 files changed

+39
-67
lines changed

2 files changed

+39
-67
lines changed

src/validators/decimal.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::errors::ErrorType;
99
use crate::errors::ValResult;
1010
use crate::errors::{ErrorTypeDefaults, Number};
1111
use crate::errors::{ToErrorValue, ValError};
12-
use crate::input::Input;
12+
use crate::input::{decimal_as_int, EitherInt, Input};
1313
use crate::tools::SchemaDict;
1414

1515
use super::{BuildValidator, CombinedValidator, DefinitionsBuilder, ValidationState, Validator};
@@ -288,3 +288,28 @@ fn handle_decimal_new_error(input: impl ToErrorValue, error: PyErr, decimal_exce
288288
ValError::InternalErr(error)
289289
}
290290
}
291+
292+
pub(crate) fn try_from_decimal_to_int<'a, 'py, I: Input<'py> + ?Sized>(
293+
py: Python<'py>,
294+
input: &'a I,
295+
) -> ValResult<Option<i64>> {
296+
let Some(py_input) = input.as_python() else {
297+
return Ok(None);
298+
};
299+
300+
if let Ok(false) = py_input.is_instance(get_decimal_type(py)) {
301+
return Ok(None);
302+
}
303+
304+
let Ok(EitherInt::Py(dec_value)) = decimal_as_int(input, py_input) else {
305+
return Ok(None);
306+
};
307+
308+
let Ok(either_int) = dec_value.exact_int() else {
309+
return Ok(None);
310+
};
311+
312+
let int = either_int.into_i64(py)?;
313+
314+
Ok(Some(int))
315+
}

src/validators/literal.rs

Lines changed: 13 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ use ahash::AHashMap;
1111

1212
use crate::build_tools::{py_schema_err, py_schema_error_type};
1313
use crate::errors::{ErrorType, ValError, ValResult};
14-
use crate::input::{decimal_as_int, EitherInt, Input, ValidationMatch};
14+
use crate::input::{Input, ValidationMatch};
1515
use crate::py_gc::PyGcTraverse;
1616
use crate::tools::SchemaDict;
1717

18-
use super::decimal::get_decimal_type;
18+
use super::decimal::try_from_decimal_to_int;
1919
use super::{BuildValidator, CombinedValidator, DefinitionsBuilder, ValidationState, Validator};
2020

2121
#[derive(Debug, Clone, Default)]
@@ -126,8 +126,11 @@ impl<T: Debug> LiteralLookup<T> {
126126
}
127127
}
128128
// if the input is a Decimal type, we need to check if its value is in the expected_ints
129-
if let Ok(Some(v)) = self.try_from_dec_to_int(py, input, expected_ints) {
130-
return Ok(Some(v));
129+
if let Ok(Some(value)) = try_from_decimal_to_int(py, input) {
130+
let Some(id) = expected_ints.get(&value) else {
131+
return Ok(None);
132+
};
133+
return Ok(Some((input, &self.values[*id])));
131134
}
132135
}
133136

@@ -150,9 +153,12 @@ impl<T: Debug> LiteralLookup<T> {
150153
}
151154
}
152155
if !strict {
153-
// if the input is a Decimal type, we need to check if its value is in the expected_strings
154-
if let Ok(Some(v)) = self.try_from_dec_to_str(py, input, expected_strings) {
155-
return Ok(Some(v));
156+
// if the input is a Decimal type, we need to check if its value is in the expected_ints
157+
if let Ok(Some(value)) = try_from_decimal_to_int(py, input) {
158+
let Some(id) = expected_strings.get(&value.to_string()) else {
159+
return Ok(None);
160+
};
161+
return Ok(Some((input, &self.values[*id])));
156162
}
157163
}
158164
}
@@ -180,65 +186,6 @@ impl<T: Debug> LiteralLookup<T> {
180186
Ok(None)
181187
}
182188

183-
fn try_from_dec_to_int<'a, 'py, I: Input<'py> + ?Sized>(
184-
&self,
185-
py: Python<'py>,
186-
input: &'a I,
187-
expected_ints: &AHashMap<i64, usize>,
188-
) -> ValResult<Option<(&'a I, &T)>> {
189-
let Some(py_input) = input.as_python() else {
190-
return Ok(None);
191-
};
192-
193-
if let Ok(false) = py_input.is_instance(get_decimal_type(py)) {
194-
return Ok(None);
195-
}
196-
197-
let Ok(EitherInt::Py(dec_value)) = decimal_as_int(input, py_input) else {
198-
return Ok(None);
199-
};
200-
201-
let Ok(either_int) = dec_value.exact_int() else {
202-
return Ok(None);
203-
};
204-
let int = either_int.into_i64(py)?;
205-
206-
let Some(id) = expected_ints.get(&int) else {
207-
return Ok(None);
208-
};
209-
210-
Ok(Some((input, &self.values[*id])))
211-
}
212-
213-
fn try_from_dec_to_str<'a, 'py, I: Input<'py> + ?Sized>(
214-
&self,
215-
py: Python<'py>,
216-
input: &'a I,
217-
expected_strings: &AHashMap<String, usize>,
218-
) -> ValResult<Option<(&'a I, &T)>> {
219-
let Some(py_input) = input.as_python() else {
220-
return Ok(None);
221-
};
222-
223-
if let Ok(false) = py_input.is_instance(get_decimal_type(py)) {
224-
return Ok(None);
225-
}
226-
227-
let Ok(EitherInt::Py(dec_value)) = decimal_as_int(input, py_input) else {
228-
return Ok(None);
229-
};
230-
231-
let Ok(either_int) = dec_value.exact_int() else {
232-
return Ok(None);
233-
};
234-
let int = either_int.into_i64(py)?;
235-
if let Some(id) = expected_strings.get(&int.to_string()) {
236-
return Ok(Some((input, &self.values[*id])));
237-
}
238-
239-
Ok(None)
240-
}
241-
242189
/// Used by int enums
243190
pub fn validate_int<'a, 'py, I: Input<'py> + ?Sized>(
244191
&self,

0 commit comments

Comments
 (0)