@@ -8,6 +8,7 @@ use futures::StreamExt;
88use futures:: stream;
99use vortex_array:: ArrayContext ;
1010use vortex_array:: ArrayRef ;
11+ use vortex_array:: ExecutionCtx ;
1112use vortex_array:: IntoArray ;
1213use vortex_array:: VortexSessionExecute ;
1314use vortex_array:: arrays:: List ;
@@ -100,23 +101,13 @@ impl LayoutStrategy for ListLayoutStrategy {
100101 } ;
101102 let ( sequence_id, array) = chunk?;
102103
103- // Run the execution loop until we have a List or ListView; skip work when the input is
104- // already in one of those forms. If the input is already a ListArray we extract its
105- // parts directly; if it's a ListViewArray we rebuild via `list_from_list_view`.
106104 let mut exec_ctx = session. create_execution_ctx ( ) ;
107- let canonical = array. execute_until :: < AnyList > ( & mut exec_ctx) ?;
108105 let ListDataParts {
109106 elements,
110107 offsets,
111108 validity,
112109 ..
113- } = if let Some ( list) = canonical. as_opt :: < List > ( ) {
114- list. into_owned ( ) . into_data_parts ( )
115- } else if let Some ( view) = canonical. as_opt :: < ListView > ( ) {
116- list_from_list_view ( view. into_owned ( ) ) ?. into_data_parts ( )
117- } else {
118- unreachable ! ( "AnyList matcher guarantees List or ListView" ) ;
119- } ;
110+ } = canonicalize_to_list_parts ( array, & mut exec_ctx) ?;
120111
121112 // There is one extra element in `offsets`
122113 let row_count = offsets. len ( ) . saturating_sub ( 1 ) ;
@@ -179,6 +170,24 @@ impl LayoutStrategy for ListLayoutStrategy {
179170 }
180171}
181172
173+ /// Canonicalize a list-dtype array into [`ListDataParts`]. Short-circuits when the input is
174+ /// already a `List` or `ListView` array — otherwise drives the execution loop until one of
175+ /// those forms appears. `ListView` is rebuilt into zero-copy-to-list form via
176+ /// [`list_from_list_view`] before its parts are extracted.
177+ fn canonicalize_to_list_parts (
178+ array : ArrayRef ,
179+ exec_ctx : & mut ExecutionCtx ,
180+ ) -> VortexResult < ListDataParts > {
181+ let canonical = array. execute_until :: < AnyList > ( exec_ctx) ?;
182+ if let Some ( list) = canonical. as_opt :: < List > ( ) {
183+ Ok ( list. into_owned ( ) . into_data_parts ( ) )
184+ } else if let Some ( view) = canonical. as_opt :: < ListView > ( ) {
185+ Ok ( list_from_list_view ( view. into_owned ( ) ) ?. into_data_parts ( ) )
186+ } else {
187+ unreachable ! ( "AnyList matcher guarantees List or ListView" )
188+ }
189+ }
190+
182191/// Wrap a single array as a one-shot [`SendableSequentialStream`] for handoff to a child writer.
183192fn single_chunk_stream (
184193 dtype : DType ,
0 commit comments