Skip to content

Commit 8f6c0f3

Browse files
committed
Fixed problem with arrays in JSONs
Signed-off-by: chandr-andr (Kiselev Aleksandr) <chandr@chandr.net>
1 parent 1244078 commit 8f6c0f3

File tree

1 file changed

+57
-39
lines changed

1 file changed

+57
-39
lines changed

src/value_converter.rs

Lines changed: 57 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -198,22 +198,6 @@ impl ToPyObject for PythonDTO {
198198
}
199199

200200
impl PythonDTO {
201-
/// Check is it possible to create serde `Value` from `PythonDTO`.
202-
#[must_use]
203-
pub fn is_available_to_serde_value(&self) -> bool {
204-
matches!(
205-
self,
206-
PythonDTO::PyNone
207-
| PythonDTO::PyBool(_)
208-
| PythonDTO::PyString(_)
209-
| PythonDTO::PyText(_)
210-
| PythonDTO::PyVarChar(_)
211-
| PythonDTO::PyIntI32(_)
212-
| PythonDTO::PyIntI64(_)
213-
| PythonDTO::PyFloat32(_)
214-
| PythonDTO::PyFloat64(_)
215-
)
216-
}
217201
/// Return type of the Array for `PostgreSQL`.
218202
///
219203
/// Since every Array must have concrete type,
@@ -285,29 +269,7 @@ impl PythonDTO {
285269

286270
Ok(json!(vec_serde_values))
287271
}
288-
PythonDTO::PyArray(array) => Python::with_gil(|gil| {
289-
if let Some(array_elem) = array.iter().nth(0) {
290-
if !array_elem.is_available_to_serde_value() {
291-
return Err(RustPSQLDriverError::PyToRustValueConversionError(
292-
"Your value in dict isn't supported by JSON".into(),
293-
));
294-
}
295-
}
296-
let py_list = postgres_array_to_py(gil, Some(array.clone()));
297-
if let Some(py_list) = py_list {
298-
let mut vec_serde_values: Vec<Value> = vec![];
299-
300-
for py_object in py_list.bind(gil) {
301-
vec_serde_values.push(py_to_rust(&py_object)?.to_serde_value()?);
302-
}
303-
304-
return Ok(json!(vec_serde_values));
305-
}
306-
307-
Err(RustPSQLDriverError::PyToRustValueConversionError(
308-
"Cannot convert Python sequence into JSON".into(),
309-
))
310-
}),
272+
PythonDTO::PyArray(array) => Ok(json!(pythondto_array_to_serde(Some(array.clone()))?)),
311273
PythonDTO::PyJsonb(py_dict) | PythonDTO::PyJson(py_dict) => Ok(py_dict.clone()),
312274
_ => Err(RustPSQLDriverError::PyToRustValueConversionError(
313275
"Cannot convert your type into Rust type".into(),
@@ -848,6 +810,62 @@ fn _composite_field_postgres_to_py<'a, T: FromSql<'a>>(
848810
})
849811
}
850812

813+
/// Convert rust array to python list.
814+
///
815+
/// It can convert multidimensional arrays.
816+
fn pythondto_array_to_serde(array: Option<Array<PythonDTO>>) -> RustPSQLDriverPyResult<Value> {
817+
match array {
818+
Some(array) => {
819+
return _pythondto_array_to_serde(
820+
array.dimensions(),
821+
array.iter().collect::<Vec<&PythonDTO>>().as_slice(),
822+
0,
823+
0,
824+
);
825+
}
826+
None => Ok(Value::Null),
827+
}
828+
}
829+
830+
/// Inner postgres array conversion to python list.
831+
#[allow(clippy::cast_sign_loss)]
832+
fn _pythondto_array_to_serde(
833+
dimensions: &[Dimension],
834+
data: &[&PythonDTO],
835+
dimension_index: usize,
836+
mut lower_bound: usize,
837+
) -> RustPSQLDriverPyResult<Value> {
838+
let current_dimension = dimensions.get(dimension_index).unwrap();
839+
840+
let possible_next_dimension = dimensions.get(dimension_index + 1);
841+
match possible_next_dimension {
842+
Some(next_dimension) => {
843+
let mut final_list: Value = Value::Array(vec![]);
844+
845+
for _ in 0..current_dimension.len as usize {
846+
if dimensions.get(dimension_index + 1).is_some() {
847+
let inner_pylist = _pythondto_array_to_serde(
848+
dimensions,
849+
&data[lower_bound..next_dimension.len as usize + lower_bound],
850+
dimension_index + 1,
851+
0,
852+
)?;
853+
match final_list {
854+
Value::Array(ref mut array) => array.push(inner_pylist),
855+
_ => unreachable!(),
856+
}
857+
lower_bound += next_dimension.len as usize;
858+
};
859+
}
860+
861+
Ok(final_list)
862+
}
863+
None => {
864+
return data.iter().map(|x| x.to_serde_value()).collect();
865+
}
866+
}
867+
}
868+
851869
/// Convert rust array to python list.
852870
///
853871
/// It can convert multidimensional arrays.

0 commit comments

Comments
 (0)