@@ -54,10 +54,9 @@ use std::{
54
54
55
55
use minijinja:: Environment ;
56
56
use serde:: Deserialize ;
57
- use serde_json:: Value ;
58
57
59
58
use crate :: {
60
- config:: { Config , Delimiter } ,
59
+ config:: { Config , Delimiter , DEFAULT_WTR_BUFFER_CAPACITY } ,
61
60
util, CliError , CliResult ,
62
61
} ;
63
62
@@ -143,14 +142,6 @@ pub fn run(argv: &[&str]) -> CliResult<()> {
143
142
. collect ( ) ;
144
143
csv:: StringRecord :: from ( sanitized_headers)
145
144
} ;
146
- let context_capacity = if args. flag_no_headers {
147
- rdr. headers ( ) ?. len ( )
148
- } else {
149
- headers. len ( )
150
- } ;
151
-
152
- // Reuse context and pre-allocate
153
- let mut context = serde_json:: Map :: with_capacity ( context_capacity) ;
154
145
155
146
// Set up output handling
156
147
let output_to_dir = args. arg_outdir . is_some ( ) ;
@@ -177,8 +168,14 @@ pub fn run(argv: &[&str]) -> CliResult<()> {
177
168
None
178
169
} else {
179
170
Some ( match args. flag_output {
180
- Some ( file) => Box :: new ( BufWriter :: new ( fs:: File :: create ( file) ?) ) as Box < dyn Write > ,
181
- None => Box :: new ( BufWriter :: new ( std:: io:: stdout ( ) ) ) as Box < dyn Write > ,
171
+ Some ( file) => Box :: new ( BufWriter :: with_capacity (
172
+ DEFAULT_WTR_BUFFER_CAPACITY ,
173
+ fs:: File :: create ( file) ?,
174
+ ) ) as Box < dyn Write > ,
175
+ None => Box :: new ( BufWriter :: with_capacity (
176
+ DEFAULT_WTR_BUFFER_CAPACITY ,
177
+ std:: io:: stdout ( ) ,
178
+ ) ) as Box < dyn Write > ,
182
179
} )
183
180
} ;
184
181
@@ -188,28 +185,34 @@ pub fn run(argv: &[&str]) -> CliResult<()> {
188
185
let mut rendered = String :: new ( ) ;
189
186
#[ allow( unused_assignments) ]
190
187
let mut outfilename = String :: new ( ) ;
188
+ let mut context = simd_json:: owned:: Object :: default ( ) ;
191
189
192
190
// Process each record
193
191
for record in rdr. records ( ) {
194
192
row_number += 1 ;
195
193
curr_record. clone_from ( & record?) ;
196
- context. clear ( ) ;
197
194
198
195
if args. flag_no_headers {
199
196
// Use numeric, column 1-based indices (e.g. _c1, _c2, etc.)
200
197
for ( i, field) in curr_record. iter ( ) . enumerate ( ) {
201
- context. insert ( format ! ( "_c{}" , i + 1 ) , Value :: String ( field. to_string ( ) ) ) ;
198
+ context. insert (
199
+ format ! ( "_c{}" , i + 1 ) ,
200
+ simd_json:: OwnedValue :: String ( field. to_owned ( ) ) ,
201
+ ) ;
202
202
}
203
203
} else {
204
204
// Use header names
205
205
for ( header, field) in headers. iter ( ) . zip ( curr_record. iter ( ) ) {
206
- context. insert ( header. to_string ( ) , Value :: String ( field. to_string ( ) ) ) ;
206
+ context. insert (
207
+ header. to_string ( ) ,
208
+ simd_json:: OwnedValue :: String ( field. to_owned ( ) ) ,
209
+ ) ;
207
210
}
208
211
}
209
212
// Always add row number to context
210
213
context. insert (
211
214
QSV_ROWNO . to_string ( ) ,
212
- Value :: Number ( serde_json :: Number :: from ( row_number) ) ,
215
+ simd_json :: OwnedValue :: from ( row_number) ,
213
216
) ;
214
217
215
218
// Render template with record data
@@ -231,8 +234,9 @@ pub fn run(argv: &[&str]) -> CliResult<()> {
231
234
write ! ( writer, "{rendered}" ) ?;
232
235
writer. flush ( ) ?;
233
236
} else if let Some ( ref mut w) = wtr {
234
- write ! ( w , "{ rendered}" ) ?;
237
+ w . write_all ( rendered. as_bytes ( ) ) ?;
235
238
}
239
+ context. clear ( ) ;
236
240
}
237
241
238
242
if let Some ( mut w) = wtr {
0 commit comments