@@ -53,19 +53,22 @@ pub async fn handle_scrape(
5353 Ok ( build_response ( request, & scrape_data) )
5454}
5555
56+ fn udp_counter_from_u32 ( value : u32 ) -> i32 {
57+ // Temporary saturation guard for UDP i32 counters. Proper type alignment across Rust and DB layers
58+ // will be addressed in docs/issues/1525-07-align-rust-and-db-types.md.
59+ i32:: try_from ( value) . unwrap_or ( i32:: MAX )
60+ }
61+
5662fn build_response ( request : & ScrapeRequest , scrape_data : & ScrapeData ) -> Response {
5763 let mut torrent_stats: Vec < TorrentScrapeStatistics > = Vec :: new ( ) ;
5864
5965 for file in & scrape_data. files {
6066 let swarm_metadata = file. 1 ;
6167
62- #[ allow( clippy:: cast_possible_truncation) ]
63- let scrape_entry = {
64- TorrentScrapeStatistics {
65- seeders : NumberOfPeers ( I32 :: new ( i64:: from ( swarm_metadata. complete ) as i32 ) ) ,
66- completed : NumberOfDownloads ( I32 :: new ( i64:: from ( swarm_metadata. downloaded ) as i32 ) ) ,
67- leechers : NumberOfPeers ( I32 :: new ( i64:: from ( swarm_metadata. incomplete ) as i32 ) ) ,
68- }
68+ let scrape_entry = TorrentScrapeStatistics {
69+ seeders : NumberOfPeers ( I32 :: new ( udp_counter_from_u32 ( swarm_metadata. complete ) ) ) ,
70+ completed : NumberOfDownloads ( I32 :: new ( udp_counter_from_u32 ( swarm_metadata. downloaded ) ) ) ,
71+ leechers : NumberOfPeers ( I32 :: new ( udp_counter_from_u32 ( swarm_metadata. incomplete ) ) ) ,
6972 } ;
7073
7174 torrent_stats. push ( scrape_entry) ;
@@ -458,4 +461,11 @@ mod tests {
458461 }
459462 }
460463 }
464+
465+ #[ test]
466+ fn should_saturate_large_download_counts_for_udp_protocol ( ) {
467+ assert_eq ! ( super :: udp_counter_from_u32( u32 :: MAX ) , i32 :: MAX ) ;
468+ assert_eq ! ( super :: udp_counter_from_u32( ( i32 :: MAX as u32 ) + 1 ) , i32 :: MAX ) ;
469+ assert_eq ! ( super :: udp_counter_from_u32( 42 ) , 42 ) ;
470+ }
461471}
0 commit comments