1- use std:: sync:: Arc ;
1+ use std:: { collections :: BTreeMap , sync:: Arc } ;
22
33use axum:: async_trait;
44use blocking:: unblock;
55use futures:: FutureExt ;
66use pyo3:: {
77 exceptions:: PyException ,
88 pyclass, pymethods,
9- types:: { IntoPyDict , PyAnyMethods , PyString , PyTuple } ,
9+ types:: { IntoPyDict , PyAnyMethods , PyList , PyString , PyTuple } ,
1010 Bound , IntoPyObjectExt , Py , PyAny , PyResult , Python ,
1111} ;
1212
1313use crate :: {
1414 base:: { schema, value} ,
1515 builder:: plan,
16+ py:: IntoPyResult ,
1617} ;
1718use anyhow:: Result ;
1819
@@ -89,6 +90,28 @@ fn basic_value_from_py_object<'py>(
8990 Ok ( result)
9091}
9192
93+ fn field_values_from_py_object < ' py > (
94+ schema : & schema:: StructSchema ,
95+ v : & Bound < ' py , PyAny > ,
96+ ) -> PyResult < value:: FieldValues > {
97+ let list = v. extract :: < Vec < Bound < ' py , PyAny > > > ( ) ?;
98+ if list. len ( ) != schema. fields . len ( ) {
99+ return Err ( PyException :: new_err ( format ! (
100+ "struct field number mismatch, expected {}, got {}" ,
101+ schema. fields. len( ) ,
102+ list. len( )
103+ ) ) ) ;
104+ }
105+ Ok ( value:: FieldValues {
106+ fields : schema
107+ . fields
108+ . iter ( )
109+ . zip ( list. into_iter ( ) )
110+ . map ( |( f, v) | value_from_py_object ( & f. value_type . typ , & v) )
111+ . collect :: < PyResult < Vec < _ > > > ( ) ?,
112+ } )
113+ }
114+
92115fn value_from_py_object < ' py > (
93116 typ : & schema:: ValueType ,
94117 v : & Bound < ' py , PyAny > ,
@@ -100,6 +123,39 @@ fn value_from_py_object<'py>(
100123 schema:: ValueType :: Basic ( typ) => {
101124 value:: Value :: Basic ( basic_value_from_py_object ( typ, v) ?)
102125 }
126+ schema:: ValueType :: Struct ( schema) => {
127+ value:: Value :: Struct ( field_values_from_py_object ( schema, v) ?)
128+ }
129+ schema:: ValueType :: Collection ( schema) => {
130+ let list = v. extract :: < Vec < Bound < ' py , PyAny > > > ( ) ?;
131+ let values = list
132+ . into_iter ( )
133+ . map ( |v| field_values_from_py_object ( & schema. row , & v) )
134+ . collect :: < PyResult < Vec < _ > > > ( ) ?;
135+ match schema. kind {
136+ schema:: CollectionKind :: Collection => {
137+ value:: Value :: Collection ( values. into_iter ( ) . map ( |v| v. into ( ) ) . collect ( ) )
138+ }
139+ schema:: CollectionKind :: List => {
140+ value:: Value :: List ( values. into_iter ( ) . map ( |v| v. into ( ) ) . collect ( ) )
141+ }
142+ schema:: CollectionKind :: Table => value:: Value :: Table (
143+ values
144+ . into_iter ( )
145+ . map ( |v| {
146+ let mut iter = v. fields . into_iter ( ) ;
147+ let key = iter. next ( ) . unwrap ( ) . to_key ( ) . into_py_result ( ) ?;
148+ Ok ( (
149+ key,
150+ value:: ScopeValue ( value:: FieldValues {
151+ fields : iter. collect :: < Vec < _ > > ( ) ,
152+ } ) ,
153+ ) )
154+ } )
155+ . collect :: < PyResult < BTreeMap < _ , _ > > > ( ) ?,
156+ ) ,
157+ }
158+ }
103159 _ => {
104160 return Err ( PyException :: new_err ( format ! (
105161 "unsupported value type: {}" ,
0 commit comments