@@ -108,7 +108,7 @@ pub(super) fn write_native_results(
108108 clippy:: too_many_lines,
109109 reason = "single-pass streaming writer needs inline path + row logic"
110110) ]
111- pub ( super ) fn write_index_streaming < W : Write > (
111+ pub ( super ) fn write_index_streaming < W : Write + ? Sized > (
112112 index : & uffs_mft:: MftIndex ,
113113 writer : & mut W ,
114114 format : & str ,
@@ -120,7 +120,6 @@ pub(super) fn write_index_streaming<W: Write>(
120120 let output_cols = selected_output_columns ( output_config) ;
121121 let tz_offset_secs = output_config. timezone_offset_secs ;
122122
123- // Build path cache (includes dir_cache for fast parent lookups).
124123 let t_cache = std:: time:: Instant :: now ( ) ;
125124 let path_cache = PathCache :: build ( index, false ) ;
126125 let resolver = path_cache. resolver ( ) ;
@@ -492,7 +491,7 @@ fn write_native_results_to<W: Write>(
492491}
493492
494493/// Write the configured header for direct native output.
495- fn write_native_header < W : Write > (
494+ fn write_native_header < W : Write + ? Sized > (
496495 writer : & mut W ,
497496 output_config : & OutputConfig ,
498497 output_cols : & [ OutputColumn ] ,
@@ -518,10 +517,50 @@ fn write_native_header<W: Write>(
518517
519518/// Return the effective output columns for the current configuration.
520519#[ must_use]
521- fn selected_output_columns ( output_config : & OutputConfig ) -> & [ OutputColumn ] {
520+ pub ( super ) fn selected_output_columns ( output_config : & OutputConfig ) -> & [ OutputColumn ] {
522521 output_config. columns . as_deref ( ) . unwrap_or ( CPP_COLUMN_ORDER )
523522}
524523
524+ /// Public wrapper for `write_native_header` (used by multi-drive streaming).
525+ #[ cfg( windows) ]
526+ pub ( super ) fn write_native_header_pub < W : Write + ?Sized > (
527+ writer : & mut W ,
528+ output_config : & OutputConfig ,
529+ output_cols : & [ OutputColumn ] ,
530+ ) -> Result < ( ) > {
531+ write_native_header ( writer, output_config, output_cols)
532+ }
533+
534+ /// Stream rows from an `MftIndex` WITHOUT writing header/footer.
535+ ///
536+ /// Used by multi-drive streaming where the caller writes one header before
537+ /// all drives and one footer after all drives.
538+ #[ cfg( windows) ]
539+ pub ( super ) fn write_index_streaming_no_header < W : Write + ?Sized > (
540+ index : & uffs_mft:: MftIndex ,
541+ writer : & mut W ,
542+ output_config : & OutputConfig ,
543+ ) -> Result < usize > {
544+ // Use a no-header OutputConfig clone and pass format="" to skip footer.
545+ let mut no_header_config = output_config. clone ( ) ;
546+ no_header_config. header = false ;
547+ let footer_ctx = CppFooterContext {
548+ output_targets : & [ ] ,
549+ pattern : "" ,
550+ row_count : 0 ,
551+ } ;
552+ write_index_streaming ( index, writer, "" , & no_header_config, & footer_ctx)
553+ }
554+
555+ /// Public wrapper for `write_cpp_drive_footer` (used by multi-drive streaming).
556+ #[ cfg( windows) ]
557+ pub ( super ) fn write_cpp_footer_pub < W : Write + ?Sized > (
558+ writer : & mut W ,
559+ ctx : & CppFooterContext < ' _ > ,
560+ ) -> Result < ( ) > {
561+ write_cpp_drive_footer ( writer, ctx)
562+ }
563+
525564/// Write a single native value using the same formatting semantics as the
526565/// `DataFrame` output path.
527566#[ expect(
@@ -1119,7 +1158,7 @@ pub(super) fn write_results(
11191158///
11201159/// Uses CRLF line endings (`\r\n`) to match C++ baseline behavior.
11211160/// When `row_count` is < 20,000, appends the fast-scan message.
1122- fn write_cpp_drive_footer < W : Write > ( writer : & mut W , ctx : & CppFooterContext < ' _ > ) -> Result < ( ) > {
1161+ fn write_cpp_drive_footer < W : Write + ? Sized > ( writer : & mut W , ctx : & CppFooterContext < ' _ > ) -> Result < ( ) > {
11231162 if ctx. output_targets . is_empty ( ) {
11241163 return Ok ( ( ) ) ;
11251164 }
0 commit comments