@@ -2,27 +2,34 @@ use crate::prelude::*;
2
2
3
3
use super :: schema:: { EnrichedValueType , FieldSchema } ;
4
4
use serde:: { Deserialize , Serialize } ;
5
- use serde_json:: Value ;
6
5
use std:: fmt;
7
6
use std:: ops:: Deref ;
8
7
9
- // Define SpecFormatMode enum for type-safe formatting
8
+ /// OutputMode enum for displaying spec info in different granularity
10
9
#[ derive( Debug , Clone , Copy , PartialEq ) ]
11
- pub enum SpecFormatMode {
10
+ pub enum OutputMode {
12
11
Concise ,
13
12
Verbose ,
14
13
}
15
14
16
- impl SpecFormatMode {
17
- pub fn from_str ( s : & str ) -> Result < Self , String > {
15
+ impl OutputMode {
16
+ pub fn from_str ( s : & str ) -> Self {
18
17
match s. to_lowercase ( ) . as_str ( ) {
19
- "concise" => Ok ( SpecFormatMode :: Concise ) ,
20
- "verbose" => Ok ( SpecFormatMode :: Verbose ) ,
21
- _ => Err ( format ! ( "Invalid format mode: {}" , s) ) ,
18
+ "concise" => OutputMode :: Concise ,
19
+ "verbose" => OutputMode :: Verbose ,
20
+ _ => unreachable ! (
21
+ "Invalid format mode: {}. Expected 'concise' or 'verbose'." ,
22
+ s
23
+ ) ,
22
24
}
23
25
}
24
26
}
25
27
28
+ /// Formatting spec per output mode
29
+ pub trait SpecFormatter {
30
+ fn format ( & self , mode : OutputMode ) -> String ;
31
+ }
32
+
26
33
#[ derive( Debug , Clone , Serialize , Deserialize ) ]
27
34
#[ serde( tag = "kind" ) ]
28
35
pub enum SpecString {
@@ -233,69 +240,31 @@ pub struct OpSpec {
233
240
pub spec : serde_json:: Map < String , serde_json:: Value > ,
234
241
}
235
242
236
- impl OpSpec {
237
- pub fn format_concise ( & self ) -> String {
238
- let mut parts = vec ! [ ] ;
239
- for ( key, value) in self . spec . iter ( ) {
240
- match value {
241
- Value :: String ( s) => parts. push ( format ! ( "{}={}" , key, s) ) ,
242
- Value :: Array ( arr) => {
243
- let items = arr
244
- . iter ( )
245
- . filter_map ( |v| v. as_str ( ) )
246
- . collect :: < Vec < _ > > ( )
247
- . join ( "," ) ;
248
- if !items. is_empty ( ) {
249
- parts. push ( format ! ( "{}={}" , key, items) ) ;
250
- }
251
- }
252
- Value :: Object ( obj) => {
253
- if let Some ( model) = obj. get ( "model" ) . and_then ( |v| v. as_str ( ) ) {
254
- parts. push ( format ! ( "{}={}" , key, model) ) ;
255
- }
256
- }
257
- _ => { }
258
- }
259
- }
260
- if parts. is_empty ( ) {
261
- self . kind . clone ( )
262
- } else {
263
- format ! ( "{}({})" , self . kind, parts. join( ", " ) )
264
- }
265
- }
266
-
267
- pub fn format_verbose ( & self ) -> String {
268
- let spec_str = serde_json:: to_string_pretty ( & self . spec )
269
- . map ( |s| {
270
- let lines: Vec < & str > = s. lines ( ) . collect ( ) ;
271
- if lines. len ( ) < s. lines ( ) . count ( ) {
272
- lines
273
- . into_iter ( )
274
- . chain ( [ "..." ] )
275
- . collect :: < Vec < _ > > ( )
276
- . join ( "\n " )
277
- } else {
278
- lines. join ( "\n " )
279
- }
280
- } )
281
- . unwrap_or ( "#serde_error" . to_string ( ) ) ;
282
- format ! ( "{}({})" , self . kind, spec_str)
283
- }
284
-
285
- pub fn format ( & self , mode : SpecFormatMode ) -> String {
243
+ impl SpecFormatter for OpSpec {
244
+ fn format ( & self , mode : OutputMode ) -> String {
286
245
match mode {
287
- SpecFormatMode :: Concise => self . format_concise ( ) ,
288
- SpecFormatMode :: Verbose => self . format_verbose ( ) ,
246
+ OutputMode :: Concise => self . kind . clone ( ) ,
247
+ OutputMode :: Verbose => {
248
+ let spec_str = serde_json:: to_string_pretty ( & self . spec )
249
+ . map ( |s| {
250
+ let lines: Vec < & str > = s. lines ( ) . collect ( ) ;
251
+ if lines. len ( ) < s. lines ( ) . count ( ) {
252
+ lines
253
+ . into_iter ( )
254
+ . chain ( [ "..." ] )
255
+ . collect :: < Vec < _ > > ( )
256
+ . join ( "\n " )
257
+ } else {
258
+ lines. join ( "\n " )
259
+ }
260
+ } )
261
+ . unwrap_or ( "#serde_error" . to_string ( ) ) ;
262
+ format ! ( "{}({})" , self . kind, spec_str)
263
+ }
289
264
}
290
265
}
291
266
}
292
267
293
- impl fmt:: Display for OpSpec {
294
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
295
- write ! ( f, "{}" , self . format_concise( ) )
296
- }
297
- }
298
-
299
268
#[ derive( Debug , Clone , Serialize , Deserialize , Default ) ]
300
269
pub struct SourceRefreshOptions {
301
270
pub refresh_interval : Option < std:: time:: Duration > ,
@@ -319,19 +288,16 @@ pub struct ImportOpSpec {
319
288
pub refresh_options : SourceRefreshOptions ,
320
289
}
321
290
322
- impl ImportOpSpec {
323
- pub fn format ( & self , mode : SpecFormatMode ) -> String {
324
- let source = match mode {
325
- SpecFormatMode :: Concise => self . source . format_concise ( ) ,
326
- SpecFormatMode :: Verbose => self . source . format_verbose ( ) ,
327
- } ;
291
+ impl SpecFormatter for ImportOpSpec {
292
+ fn format ( & self , mode : OutputMode ) -> String {
293
+ let source = self . source . format ( mode) ;
328
294
format ! ( "source={}, refresh={}" , source, self . refresh_options)
329
295
}
330
296
}
331
297
332
298
impl fmt:: Display for ImportOpSpec {
333
299
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
334
- write ! ( f, "{}" , self . format( SpecFormatMode :: Concise ) )
300
+ write ! ( f, "{}" , self . format( OutputMode :: Concise ) )
335
301
}
336
302
}
337
303
@@ -341,31 +307,22 @@ pub struct TransformOpSpec {
341
307
pub op : OpSpec ,
342
308
}
343
309
344
- impl TransformOpSpec {
345
- pub fn format ( & self , mode : SpecFormatMode ) -> String {
310
+ impl SpecFormatter for TransformOpSpec {
311
+ fn format ( & self , mode : OutputMode ) -> String {
346
312
let inputs = self
347
313
. inputs
348
314
. iter ( )
349
315
. map ( ToString :: to_string)
350
316
. collect :: < Vec < _ > > ( )
351
317
. join ( "," ) ;
352
- let op_str = match mode {
353
- SpecFormatMode :: Concise => self . op . format_concise ( ) ,
354
- SpecFormatMode :: Verbose => self . op . format_verbose ( ) ,
355
- } ;
318
+ let op_str = self . op . format ( mode) ;
356
319
match mode {
357
- SpecFormatMode :: Concise => format ! ( "op={}, inputs={}" , op_str, inputs) ,
358
- SpecFormatMode :: Verbose => format ! ( "op={}, inputs=[{}]" , op_str, inputs) ,
320
+ OutputMode :: Concise => format ! ( "op={}, inputs={}" , op_str, inputs) ,
321
+ OutputMode :: Verbose => format ! ( "op={}, inputs=[{}]" , op_str, inputs) ,
359
322
}
360
323
}
361
324
}
362
325
363
- impl fmt:: Display for TransformOpSpec {
364
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
365
- write ! ( f, "{}" , self . format( SpecFormatMode :: Concise ) )
366
- }
367
- }
368
-
369
326
#[ derive( Debug , Clone , Serialize , Deserialize ) ]
370
327
pub struct ForEachOpSpec {
371
328
/// Mapping that provides a table to apply reactive operations to.
@@ -377,21 +334,17 @@ impl ForEachOpSpec {
377
334
pub fn get_label ( & self ) -> String {
378
335
format ! ( "Loop over {}" , self . field_path)
379
336
}
337
+ }
380
338
381
- pub fn format ( & self , mode : SpecFormatMode ) -> String {
339
+ impl SpecFormatter for ForEachOpSpec {
340
+ fn format ( & self , mode : OutputMode ) -> String {
382
341
match mode {
383
- SpecFormatMode :: Concise => self . get_label ( ) ,
384
- SpecFormatMode :: Verbose => format ! ( "field={}" , self . field_path) ,
342
+ OutputMode :: Concise => self . get_label ( ) ,
343
+ OutputMode :: Verbose => format ! ( "field={}" , self . field_path) ,
385
344
}
386
345
}
387
346
}
388
347
389
- impl fmt:: Display for ForEachOpSpec {
390
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
391
- write ! ( f, "field={}" , self . field_path)
392
- }
393
- }
394
-
395
348
#[ derive( Debug , Clone , Serialize , Deserialize ) ]
396
349
pub struct CollectOpSpec {
397
350
/// Field values to be collected.
@@ -405,17 +358,17 @@ pub struct CollectOpSpec {
405
358
pub auto_uuid_field : Option < FieldName > ,
406
359
}
407
360
408
- impl CollectOpSpec {
409
- pub fn format ( & self , mode : SpecFormatMode ) -> String {
361
+ impl SpecFormatter for CollectOpSpec {
362
+ fn format ( & self , mode : OutputMode ) -> String {
410
363
let uuid = self . auto_uuid_field . as_deref ( ) . unwrap_or ( "none" ) ;
411
364
match mode {
412
- SpecFormatMode :: Concise => {
365
+ OutputMode :: Concise => {
413
366
format ! (
414
367
"collector={}, input={}, uuid={}" ,
415
368
self . collector_name, self . input, uuid
416
369
)
417
370
}
418
- SpecFormatMode :: Verbose => {
371
+ OutputMode :: Verbose => {
419
372
format ! (
420
373
"scope={}, collector={}, input=[{}], uuid={}" ,
421
374
self . scope_name, self . collector_name, self . input, uuid
@@ -425,12 +378,6 @@ impl CollectOpSpec {
425
378
}
426
379
}
427
380
428
- impl fmt:: Display for CollectOpSpec {
429
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
430
- write ! ( f, "{}" , self . format( SpecFormatMode :: Concise ) )
431
- }
432
- }
433
-
434
381
#[ derive( Debug , Clone , Copy , Serialize , Deserialize , PartialEq , Eq ) ]
435
382
pub enum VectorSimilarityMetric {
436
383
CosineSimilarity ,
@@ -493,29 +440,20 @@ pub struct ExportOpSpec {
493
440
pub setup_by_user : bool ,
494
441
}
495
442
496
- impl ExportOpSpec {
497
- pub fn format ( & self , mode : SpecFormatMode ) -> String {
498
- let target_str = match mode {
499
- SpecFormatMode :: Concise => self . target . format_concise ( ) ,
500
- SpecFormatMode :: Verbose => self . target . format_verbose ( ) ,
501
- } ;
443
+ impl SpecFormatter for ExportOpSpec {
444
+ fn format ( & self , mode : OutputMode ) -> String {
445
+ let target_str = self . target . format ( mode) ;
502
446
let base = format ! (
503
447
"collector={}, target={}, {}" ,
504
448
self . collector_name, target_str, self . index_options
505
449
) ;
506
450
match mode {
507
- SpecFormatMode :: Concise => base,
508
- SpecFormatMode :: Verbose => format ! ( "{}, setup_by_user={}" , base, self . setup_by_user) ,
451
+ OutputMode :: Concise => base,
452
+ OutputMode :: Verbose => format ! ( "{}, setup_by_user={}" , base, self . setup_by_user) ,
509
453
}
510
454
}
511
455
}
512
456
513
- impl fmt:: Display for ExportOpSpec {
514
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
515
- write ! ( f, "{}" , self . format( SpecFormatMode :: Concise ) )
516
- }
517
- }
518
-
519
457
#[ derive( Debug , Clone , Serialize , Deserialize ) ]
520
458
#[ serde( tag = "action" ) ]
521
459
pub enum ReactiveOpSpec {
@@ -524,25 +462,19 @@ pub enum ReactiveOpSpec {
524
462
Collect ( CollectOpSpec ) ,
525
463
}
526
464
527
- impl ReactiveOpSpec {
528
- pub fn format ( & self , mode : SpecFormatMode ) -> String {
465
+ impl SpecFormatter for ReactiveOpSpec {
466
+ fn format ( & self , mode : OutputMode ) -> String {
529
467
match self {
530
468
ReactiveOpSpec :: Transform ( t) => format ! ( "Transform: {}" , t. format( mode) ) ,
531
469
ReactiveOpSpec :: ForEach ( fe) => match mode {
532
- SpecFormatMode :: Concise => format ! ( "{}" , fe. get_label( ) ) ,
533
- SpecFormatMode :: Verbose => format ! ( "ForEach: {}" , fe. format( mode) ) ,
470
+ OutputMode :: Concise => format ! ( "{}" , fe. get_label( ) ) ,
471
+ OutputMode :: Verbose => format ! ( "ForEach: {}" , fe. format( mode) ) ,
534
472
} ,
535
473
ReactiveOpSpec :: Collect ( c) => format ! ( "Collect: {}" , c. format( mode) ) ,
536
474
}
537
475
}
538
476
}
539
477
540
- impl fmt:: Display for ReactiveOpSpec {
541
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
542
- write ! ( f, "{}" , self . format( SpecFormatMode :: Concise ) )
543
- }
544
- }
545
-
546
478
#[ derive( Debug , Clone , Serialize , Deserialize ) ]
547
479
pub struct ReactiveOpScope {
548
480
pub name : ScopeName ,
0 commit comments