1
+ use anyhow:: anyhow;
1
2
use chrono:: { DateTime , Utc } ;
2
3
use serde:: { Deserialize , Serialize } ;
3
4
4
5
use crate :: entities:: {
5
6
AncillaryLocation , AncillaryLocations , CardanoDbBeacon , CompressionAlgorithm , DigestLocation ,
6
7
DigestsLocations , Epoch , ImmutablesLocation , ImmutablesLocations , MultiFilesUri , TemplateUri ,
7
8
} ;
9
+ use crate :: StdResult ;
8
10
9
11
/// The message part that represents the locations of the Cardano database digests.
10
12
#[ derive( Clone , Debug , Default , PartialEq , Eq , Serialize , Deserialize ) ]
@@ -15,6 +17,25 @@ pub struct DigestsMessagePart {
15
17
/// Locations of the digests.
16
18
pub locations : Vec < DigestLocation > ,
17
19
}
20
+
21
+ impl DigestsMessagePart {
22
+ /// Return the list of locations without the unknown locations, failing if all locations are unknown.
23
+ pub fn sanitized_locations ( & self ) -> StdResult < Vec < DigestLocation > > {
24
+ let sanitized_locations: Vec < _ > = self
25
+ . locations
26
+ . iter ( )
27
+ . filter ( |l| !matches ! ( l, DigestLocation :: Unknown ) )
28
+ . cloned ( )
29
+ . collect ( ) ;
30
+
31
+ if sanitized_locations. is_empty ( ) {
32
+ Err ( anyhow ! ( "All digests locations are unknown." ) )
33
+ } else {
34
+ Ok ( sanitized_locations)
35
+ }
36
+ }
37
+ }
38
+
18
39
/// The message part that represents the locations of the Cardano database immutables.
19
40
#[ derive( Clone , Debug , Default , PartialEq , Eq , Serialize , Deserialize ) ]
20
41
pub struct ImmutablesMessagePart {
@@ -24,6 +45,25 @@ pub struct ImmutablesMessagePart {
24
45
/// Locations of the immutable files.
25
46
pub locations : Vec < ImmutablesLocation > ,
26
47
}
48
+
49
+ impl ImmutablesMessagePart {
50
+ /// Return the list of locations without the unknown locations, failing if all locations are unknown.
51
+ pub fn sanitized_locations ( & self ) -> StdResult < Vec < ImmutablesLocation > > {
52
+ let sanitized_locations: Vec < _ > = self
53
+ . locations
54
+ . iter ( )
55
+ . filter ( |l| !matches ! ( l, ImmutablesLocation :: Unknown ) )
56
+ . cloned ( )
57
+ . collect ( ) ;
58
+
59
+ if sanitized_locations. is_empty ( ) {
60
+ Err ( anyhow ! ( "All locations are unknown." ) )
61
+ } else {
62
+ Ok ( sanitized_locations)
63
+ }
64
+ }
65
+ }
66
+
27
67
/// The message part that represents the locations of the Cardano database ancillary.
28
68
#[ derive( Clone , Debug , Default , PartialEq , Eq , Serialize , Deserialize ) ]
29
69
pub struct AncillaryMessagePart {
@@ -34,6 +74,24 @@ pub struct AncillaryMessagePart {
34
74
pub locations : Vec < AncillaryLocation > ,
35
75
}
36
76
77
+ impl AncillaryMessagePart {
78
+ /// Return the list of locations without the unknown locations, failing if all locations are unknown.
79
+ pub fn sanitized_locations ( & self ) -> StdResult < Vec < AncillaryLocation > > {
80
+ let sanitized_locations: Vec < _ > = self
81
+ . locations
82
+ . iter ( )
83
+ . filter ( |l| !matches ! ( l, AncillaryLocation :: Unknown ) )
84
+ . cloned ( )
85
+ . collect ( ) ;
86
+
87
+ if sanitized_locations. is_empty ( ) {
88
+ Err ( anyhow ! ( "All locations are unknown." ) )
89
+ } else {
90
+ Ok ( sanitized_locations)
91
+ }
92
+ }
93
+ }
94
+
37
95
impl From < DigestsLocations > for DigestsMessagePart {
38
96
fn from ( part : DigestsLocations ) -> Self {
39
97
Self {
@@ -324,4 +382,175 @@ mod tests {
324
382
assert_eq ! ( message. ancillary. locations. len( ) , 1 ) ;
325
383
assert_eq ! ( AncillaryLocation :: Unknown , message. ancillary. locations[ 0 ] ) ;
326
384
}
385
+
386
+ mod sanitize_immutable_locations {
387
+ use super :: * ;
388
+
389
+ #[ test]
390
+ fn succeeds_and_leave_all_locations_intact_if_no_unknown_location ( ) {
391
+ let immutable_locations = ImmutablesMessagePart {
392
+ locations : vec ! [ ImmutablesLocation :: CloudStorage {
393
+ uri: MultiFilesUri :: Template ( TemplateUri (
394
+ "http://whatever/{immutable_file_number}.tar.gz" . to_string( ) ,
395
+ ) ) ,
396
+ compression_algorithm: None ,
397
+ } ] ,
398
+ average_size_uncompressed : 512 ,
399
+ } ;
400
+
401
+ let sanitize_locations = immutable_locations
402
+ . sanitized_locations ( )
403
+ . expect ( "Should succeed since there are no unknown locations." ) ;
404
+ assert_eq ! ( sanitize_locations, immutable_locations. locations) ;
405
+ }
406
+
407
+ #[ test]
408
+ fn succeeds_and_remove_unknown_locations_if_some_locations_are_not_unknown ( ) {
409
+ let immutable_locations = ImmutablesMessagePart {
410
+ locations : vec ! [
411
+ ImmutablesLocation :: CloudStorage {
412
+ uri: MultiFilesUri :: Template ( TemplateUri (
413
+ "http://whatever/{immutable_file_number}.tar.gz" . to_string( ) ,
414
+ ) ) ,
415
+ compression_algorithm: None ,
416
+ } ,
417
+ ImmutablesLocation :: Unknown ,
418
+ ] ,
419
+ average_size_uncompressed : 512 ,
420
+ } ;
421
+
422
+ let sanitize_locations = immutable_locations
423
+ . sanitized_locations ( )
424
+ . expect ( "Should succeed since not all locations are unknown." ) ;
425
+ assert_eq ! (
426
+ sanitize_locations,
427
+ vec![ ImmutablesLocation :: CloudStorage {
428
+ uri: MultiFilesUri :: Template ( TemplateUri (
429
+ "http://whatever/{immutable_file_number}.tar.gz" . to_string( ) ,
430
+ ) ) ,
431
+ compression_algorithm: None ,
432
+ } ]
433
+ ) ;
434
+ }
435
+
436
+ #[ test]
437
+ fn fails_if_all_locations_are_unknown ( ) {
438
+ ImmutablesMessagePart {
439
+ locations : vec ! [ ImmutablesLocation :: Unknown ] ,
440
+ average_size_uncompressed : 512 ,
441
+ }
442
+ . sanitized_locations ( )
443
+ . expect_err ( "Should fail since all locations are unknown." ) ;
444
+ }
445
+ }
446
+
447
+ mod sanitize_ancillary_locations {
448
+ use super :: * ;
449
+
450
+ #[ test]
451
+ fn succeeds_and_leave_all_locations_intact_if_no_unknown_location ( ) {
452
+ let ancillary_locations = AncillaryMessagePart {
453
+ locations : vec ! [ AncillaryLocation :: CloudStorage {
454
+ uri: "http://whatever/ancillary.tar.gz" . to_string( ) ,
455
+ compression_algorithm: None ,
456
+ } ] ,
457
+ size_uncompressed : 1024 ,
458
+ } ;
459
+
460
+ let sanitize_locations = ancillary_locations
461
+ . sanitized_locations ( )
462
+ . expect ( "Should succeed since there are no unknown locations." ) ;
463
+ assert_eq ! ( sanitize_locations, ancillary_locations. locations) ;
464
+ }
465
+
466
+ #[ test]
467
+ fn succeeds_and_remove_unknown_locations_if_some_locations_are_not_unknown ( ) {
468
+ let ancillary_locations = AncillaryMessagePart {
469
+ locations : vec ! [
470
+ AncillaryLocation :: CloudStorage {
471
+ uri: "http://whatever/digests.tar.gz" . to_string( ) ,
472
+ compression_algorithm: None ,
473
+ } ,
474
+ AncillaryLocation :: Unknown ,
475
+ ] ,
476
+ size_uncompressed : 512 ,
477
+ } ;
478
+
479
+ let sanitize_locations = ancillary_locations
480
+ . sanitized_locations ( )
481
+ . expect ( "Should succeed since not all locations are unknown." ) ;
482
+ assert_eq ! (
483
+ sanitize_locations,
484
+ vec![ AncillaryLocation :: CloudStorage {
485
+ uri: "http://whatever/digests.tar.gz" . to_string( ) ,
486
+ compression_algorithm: None ,
487
+ } ]
488
+ ) ;
489
+ }
490
+
491
+ #[ test]
492
+ fn fails_if_all_locations_are_unknown ( ) {
493
+ AncillaryMessagePart {
494
+ locations : vec ! [ AncillaryLocation :: Unknown ] ,
495
+ size_uncompressed : 512 ,
496
+ }
497
+ . sanitized_locations ( )
498
+ . expect_err ( "Should fail since all locations are unknown." ) ;
499
+ }
500
+ }
501
+
502
+ mod sanitize_digests_locations {
503
+ use super :: * ;
504
+
505
+ #[ test]
506
+ fn succeeds_and_leave_all_locations_intact_if_no_unknown_location ( ) {
507
+ let digests_locations = DigestsMessagePart {
508
+ locations : vec ! [ DigestLocation :: CloudStorage {
509
+ uri: "http://whatever/digests.tar.gz" . to_string( ) ,
510
+ compression_algorithm: None ,
511
+ } ] ,
512
+ size_uncompressed : 512 ,
513
+ } ;
514
+
515
+ let sanitize_locations = digests_locations
516
+ . sanitized_locations ( )
517
+ . expect ( "Should succeed since there are no unknown locations." ) ;
518
+ assert_eq ! ( sanitize_locations, digests_locations. locations) ;
519
+ }
520
+
521
+ #[ test]
522
+ fn succeeds_and_remove_unknown_locations_if_some_locations_are_not_unknown ( ) {
523
+ let digests_locations = DigestsMessagePart {
524
+ locations : vec ! [
525
+ DigestLocation :: CloudStorage {
526
+ uri: "http://whatever/digests.tar.gz" . to_string( ) ,
527
+ compression_algorithm: None ,
528
+ } ,
529
+ DigestLocation :: Unknown ,
530
+ ] ,
531
+ size_uncompressed : 512 ,
532
+ } ;
533
+
534
+ let sanitize_locations = digests_locations
535
+ . sanitized_locations ( )
536
+ . expect ( "Should succeed since not all locations are unknown." ) ;
537
+ assert_eq ! (
538
+ sanitize_locations,
539
+ vec![ DigestLocation :: CloudStorage {
540
+ uri: "http://whatever/digests.tar.gz" . to_string( ) ,
541
+ compression_algorithm: None ,
542
+ } ]
543
+ ) ;
544
+ }
545
+
546
+ #[ test]
547
+ fn fails_if_all_locations_are_unknown ( ) {
548
+ DigestsMessagePart {
549
+ locations : vec ! [ DigestLocation :: Unknown ] ,
550
+ size_uncompressed : 512 ,
551
+ }
552
+ . sanitized_locations ( )
553
+ . expect_err ( "Should fail since all locations are unknown." ) ;
554
+ }
555
+ }
327
556
}
0 commit comments