From 867cd83327f48b211e020da5bd94cf9683d3f107 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Tchilinguirian?= Date: Thu, 27 Nov 2025 23:58:50 +0100 Subject: [PATCH 01/11] refactor: fix clippy uninlined_format_args --- src/contact_plan/from_asabr_lexer.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/contact_plan/from_asabr_lexer.rs b/src/contact_plan/from_asabr_lexer.rs index 80a0980..8d86ede 100644 --- a/src/contact_plan/from_asabr_lexer.rs +++ b/src/contact_plan/from_asabr_lexer.rs @@ -64,10 +64,10 @@ impl ASABRContactPlan { let node_name = node.get_node_name(); if known_node_ids.contains(&node_id) { - return Err(format!("Two nodes have the same id ({})", node_id)); + return Err(format!("Two nodes have the same id ({node_id})")); } if known_node_names.contains(&node_name) { - return Err(format!("Two nodes have the same id ({})", node_name)); + return Err(format!("Two nodes have the same id ({node_name})")); } let value = max(node.get_node_id(), node.get_node_id()); *max_node_in_in_nodes = max(*max_node_in_in_nodes, value.into()); From 8610e5bf1e1bdad2461c826224cdea756a9f9374 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Tchilinguirian?= Date: Fri, 28 Nov 2025 00:01:24 +0100 Subject: [PATCH 02/11] refactor: fix clippy needless_return --- src/node_manager/none.rs | 4 ++-- src/pathfinding/limiting_contact/first_depleted.rs | 2 +- src/pathfinding/limiting_contact/first_ending.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/node_manager/none.rs b/src/node_manager/none.rs index e0e2862..b8d5770 100644 --- a/src/node_manager/none.rs +++ b/src/node_manager/none.rs @@ -13,7 +13,7 @@ pub struct NoManagement {} impl NodeManager for NoManagement { #[cfg(feature = "node_proc")] fn dry_run_process(&self, at_time: Date, _bundle: &mut Bundle) -> Date { - return at_time; + at_time } #[cfg(feature = "node_tx")] fn dry_run_tx(&self, _waiting_since: Date, _start: Date, _end: Date, _bundle: &Bundle) -> bool { @@ -25,7 +25,7 @@ impl NodeManager for NoManagement { } #[cfg(feature = "node_proc")] fn schedule_process(&self, at_time: Date, _bundle: &mut Bundle) -> Date { - return at_time; + at_time } #[cfg(feature = "node_tx")] fn schedule_tx( diff --git a/src/pathfinding/limiting_contact/first_depleted.rs b/src/pathfinding/limiting_contact/first_depleted.rs index f0460d6..c173fb2 100644 --- a/src/pathfinding/limiting_contact/first_depleted.rs +++ b/src/pathfinding/limiting_contact/first_depleted.rs @@ -20,7 +20,7 @@ fn had_less_volume_than( a: &Contact, b: &Contact, ) -> bool { - return a.manager.get_original_volume() < b.manager.get_original_volume(); + a.manager.get_original_volume() < b.manager.get_original_volume() } create_new_alternative_path_variant!(FirstDepleted, had_less_volume_than); diff --git a/src/pathfinding/limiting_contact/first_ending.rs b/src/pathfinding/limiting_contact/first_ending.rs index 6e1be40..d5baad6 100644 --- a/src/pathfinding/limiting_contact/first_ending.rs +++ b/src/pathfinding/limiting_contact/first_ending.rs @@ -20,7 +20,7 @@ fn ends_earlier_than( a: &Contact, b: &Contact, ) -> bool { - return a.info.end < b.info.end; + a.info.end < b.info.end } create_new_alternative_path_variant!(FirstEnding, ends_earlier_than); From e76c292fbfd8def175f21c48da00ecb08350eb66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Tchilinguirian?= Date: Fri, 28 Nov 2025 00:02:24 +0100 Subject: [PATCH 03/11] refactor: fix clippy redundant_field_names --- src/route_stage.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/route_stage.rs b/src/route_stage.rs index 7d14960..9877dcd 100644 --- a/src/route_stage.rs +++ b/src/route_stage.rs @@ -96,7 +96,7 @@ impl RouteStage { route_initialized: false, next_for_destination: HashMap::new(), #[cfg(feature = "node_proc")] - bundle: bundle, + bundle, } } From 05e61ebb40d51ee4c5d78922af682fcb1e3cce5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Tchilinguirian?= Date: Sat, 6 Dec 2025 21:04:54 +0100 Subject: [PATCH 04/11] refactor: fix clippy new_without_default Implement Default for types with a new() method. --- src/parsing.rs | 6 ++++++ src/route_storage/table.rs | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/src/parsing.rs b/src/parsing.rs index c414bd9..81049a8 100644 --- a/src/parsing.rs +++ b/src/parsing.rs @@ -16,6 +16,12 @@ pub struct Dispatcher<'a, T> { /// A hashmap that stores the coercion functions with their associated markers. map: HashMap<&'a str, T>, } +impl<'a, T> Default for Dispatcher<'a, T> { + fn default() -> Self { + Self::new() + } +} + impl<'a, T> Dispatcher<'a, T> { /// Creates a new, empty `Dispatcher`. pub fn new() -> Self { diff --git a/src/route_storage/table.rs b/src/route_storage/table.rs index e30dbc8..e05d9ee 100644 --- a/src/route_storage/table.rs +++ b/src/route_storage/table.rs @@ -31,6 +31,12 @@ pub struct RoutingTable _phantom_distance: PhantomData, } +impl> Default for RoutingTable { + fn default() -> Self { + Self::new() + } +} + impl> RoutingTable { /// Creates a new, empty `RoutingTable`. /// From a81bebec1f1290b07615ad4e54005933b1b94ddc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Tchilinguirian?= Date: Fri, 26 Dec 2025 17:00:21 +0100 Subject: [PATCH 05/11] refactor: use SharedRouteStage where relevant Clippy warned about type complexity regarding Rc>>. This commit fixes some of these specific warnings. This commit introduces a new public type `SharedRouteStage`: `pub type SharedRouteStage = Rc>>;` And replaces the code where it felt it improved readability / cognitive load. --- src/contact.rs | 8 +--- src/pathfinding/hybrid_parenting.rs | 16 ++++---- src/pathfinding/limiting_contact/mod.rs | 4 +- src/pathfinding/mod.rs | 13 ++++--- src/route_stage.rs | 8 ++-- src/route_storage/mod.rs | 6 +-- src/routing/mod.rs | 51 ++++++++----------------- src/utils/mod.rs | 4 +- 8 files changed, 45 insertions(+), 65 deletions(-) diff --git a/src/contact.rs b/src/contact.rs index 82dbea3..5956a03 100644 --- a/src/contact.rs +++ b/src/contact.rs @@ -2,14 +2,10 @@ use crate::contact_manager::ContactManager; use crate::node_manager::NodeManager; use crate::parsing::{Lexer, Parser, ParsingState}; #[cfg(feature = "contact_work_area")] -use crate::route_stage::RouteStage; +use crate::route_stage::SharedRouteStage; use crate::types::{Date, NodeID, Token}; -#[cfg(feature = "contact_work_area")] -use std::cell::RefCell; use std::cmp::Ordering; use std::marker::PhantomData; -#[cfg(feature = "contact_work_area")] -use std::rc::Rc; /// Represents basic information about a contact between two nodes. #[derive(Clone, Copy)] @@ -70,7 +66,7 @@ pub struct Contact { pub manager: CM, #[cfg(feature = "contact_work_area")] /// The work area for managing path construction stages (compilation option). - pub work_area: Option>>>, + pub work_area: Option>, #[cfg(feature = "contact_suppression")] /// Suppression option for path construction (compilation option). pub suppressed: bool, diff --git a/src/pathfinding/hybrid_parenting.rs b/src/pathfinding/hybrid_parenting.rs index 4b6b1d8..c0f03cf 100644 --- a/src/pathfinding/hybrid_parenting.rs +++ b/src/pathfinding/hybrid_parenting.rs @@ -12,7 +12,7 @@ use crate::{ distance::{Distance, DistanceWrapper}, multigraph::Multigraph, node_manager::NodeManager, - route_stage::RouteStage, + route_stage::{RouteStage, SharedRouteStage}, types::{Date, NodeID}, }; @@ -66,13 +66,13 @@ struct HybridParentingWorkArea { /// The bundle associated with this work area. pub bundle: Bundle, /// The source route stage, representing the starting point for routing. - pub source: Rc>>, + pub source: SharedRouteStage, /// A sorted list of node IDs to be excluded from routing paths. pub excluded_nodes_sorted: Vec, /// A vector containing vectors of route stages, grouped by destination. /// Each inner vector represents possible routes to a specific destination, /// sorted in order of preference. - pub by_destination: Vec>>>>, + pub by_destination: Vec>>, } impl HybridParentingWorkArea { @@ -81,7 +81,7 @@ impl HybridParentingWorkArea { /// /// # Parameters /// - `bundle`: A reference to the `Bundle` representing the data payload for routing. - /// - `source`: An `Rc>>` reference to the initial route stage. + /// - `source`: A `SharedRouteStage` reference to the initial route stage. /// - `excluded_nodes_sorted`: A reference to a sorted vector of `NodeID`s to be excluded from routing paths. /// - `node_count`: The number of destination nodes, which determines the size of `by_destination`. /// @@ -89,7 +89,7 @@ impl HybridParentingWorkArea { /// A new instance of `HybridParentingWorkArea` initialized with the provided parameters. pub fn new( bundle: &Bundle, - source: Rc>>, + source: SharedRouteStage, excluded_nodes_sorted: &[NodeID], node_count: usize, ) -> Self { @@ -146,7 +146,7 @@ use super::{try_make_hop, PathFindingOutput, Pathfinding}; /// /// # Returns /// -/// * `Option>>>` - Returns an `Option` containing a reference to the +/// * `Option>` - Returns an `Option` containing a reference to the /// newly inserted route if the insertion was successful; otherwise, returns `None`. fn try_insert< NM: NodeManager, @@ -155,7 +155,7 @@ fn try_insert< >( proposition: RouteStage, tree: &mut HybridParentingWorkArea, -) -> Option>>> { +) -> Option> { let routes_for_rx_node = &mut tree.by_destination[proposition.to_node as usize]; // if D::can_retain sets insert to true, but the next element does not trigger insert_index =idx, insert at the end let mut insert_index: usize = routes_for_rx_node.len(); @@ -290,7 +290,7 @@ macro_rules! define_mpt { if $with_exclusions { graph.prepare_for_exclusions_sorted(excluded_nodes_sorted); } - let source_route: Rc>> = + let source_route: SharedRouteStage = Rc::new(RefCell::new(RouteStage::new( current_time, source, diff --git a/src/pathfinding/limiting_contact/mod.rs b/src/pathfinding/limiting_contact/mod.rs index d88af32..4cca617 100644 --- a/src/pathfinding/limiting_contact/mod.rs +++ b/src/pathfinding/limiting_contact/mod.rs @@ -1,7 +1,7 @@ use crate::contact::Contact; use crate::contact_manager::ContactManager; use crate::node_manager::NodeManager; -use crate::route_stage::RouteStage; +use crate::route_stage::SharedRouteStage; use std::cell::RefCell; use std::rc::Rc; @@ -32,7 +32,7 @@ pub use first_ending::FirstEnding; /// is found; otherwise, `None`. #[cfg(feature = "contact_suppression")] pub fn get_next_to_suppress( - route: Rc>>, + route: SharedRouteStage, better_for_suppression_than_fn: fn(&Contact, &Contact) -> bool, ) -> Option>>> { let mut to_suppress_opt: Option>>> = None; diff --git a/src/pathfinding/mod.rs b/src/pathfinding/mod.rs index 3e6a22d..ec1eece 100644 --- a/src/pathfinding/mod.rs +++ b/src/pathfinding/mod.rs @@ -1,11 +1,12 @@ +use crate::bundle::Bundle; use crate::contact::Contact; use crate::contact_manager::{ContactManager, ContactManagerTxData}; use crate::multigraph::Multigraph; use crate::node::Node; use crate::node_manager::NodeManager; use crate::route_stage::ViaHop; +use crate::route_stage::{RouteStage, SharedRouteStage}; use crate::types::{Date, NodeID}; -use crate::{bundle::Bundle, route_stage::RouteStage}; use std::cell::RefCell; use std::rc::Rc; @@ -29,11 +30,11 @@ pub struct PathFindingOutput { /// The `Bundle` for which the pathfinding is being performed. pub bundle: Bundle, /// The `source` RouteStage from which the pathfinding is being performed. - pub source: Rc>>, + pub source: SharedRouteStage, /// A list of `NodeID`s representing nodes that should be excluded from the pathfinding. pub excluded_nodes_sorted: Vec, /// A vector that contains a `RouteStage`s for a specific destination node ID as the index. - pub by_destination: Vec>>>>, + pub by_destination: Vec>>, } impl PathFindingOutput { @@ -52,7 +53,7 @@ impl PathFindingOutput { /// A new `PathfindingOutput` instance. pub fn new( bundle: &Bundle, - source: Rc>>, + source: SharedRouteStage, excluded_nodes_sorted: &[NodeID], node_count: usize, ) -> Self { @@ -65,7 +66,7 @@ impl PathFindingOutput { } } - pub fn get_source_route(&self) -> Rc>> { + pub fn get_source_route(&self) -> SharedRouteStage { self.source.clone() } @@ -148,7 +149,7 @@ pub trait Pathfinding { /// An `Option` containing a `RouteStage` if a suitable hop is found, or `None` if no valid hop is available. fn try_make_hop( first_contact_index: usize, - sndr_route: &Rc>>, + sndr_route: &SharedRouteStage, _bundle: &Bundle, contacts: &[Rc>>], tx_node: &Rc>>, diff --git a/src/route_stage.rs b/src/route_stage.rs index 9877dcd..10cbc50 100644 --- a/src/route_stage.rs +++ b/src/route_stage.rs @@ -60,13 +60,15 @@ pub struct RouteStage { /// A hashmap that maps destination node IDs to their respective next route stages. #[cfg_attr(feature = "debug", derivative(Debug = "ignore"))] // avoid cyclic print with debug formatting - pub next_for_destination: HashMap>>>, + pub next_for_destination: HashMap>, #[cfg(feature = "node_proc")] /// The stage of the bundle that arrives at to_node pub bundle: Bundle, } +pub type SharedRouteStage = Rc>>; + impl RouteStage { /// Creates a new `RouteStage` with the specified parameters. /// @@ -117,7 +119,7 @@ impl RouteStage { route } - pub fn init_route(route: Rc>>) { + pub fn init_route(route: SharedRouteStage) { let destination = route.borrow().to_node; { if route.borrow().route_initialized { @@ -125,7 +127,7 @@ impl RouteStage { } } - let mut curr_opt: Option>>> = Some(route.clone()); + let mut curr_opt: Option> = Some(route.clone()); while let Some(current) = curr_opt.take() { let route_borrowed = current.borrow_mut(); diff --git a/src/route_storage/mod.rs b/src/route_storage/mod.rs index f7d39e8..f21bfe4 100644 --- a/src/route_storage/mod.rs +++ b/src/route_storage/mod.rs @@ -9,7 +9,7 @@ use crate::{ multigraph::Multigraph, node_manager::NodeManager, pathfinding::PathFindingOutput, - route_stage::RouteStage, + route_stage::SharedRouteStage, types::{Date, NodeID, Priority, Volume}, }; @@ -52,8 +52,8 @@ pub trait TreeStorage { #[cfg_attr(feature = "debug", derive(Debug))] pub struct Route { - pub source_stage: Rc>>, - pub destination_stage: Rc>>, + pub source_stage: SharedRouteStage, + pub destination_stage: SharedRouteStage, } impl Route { diff --git a/src/routing/mod.rs b/src/routing/mod.rs index c0427d7..a53b814 100644 --- a/src/routing/mod.rs +++ b/src/routing/mod.rs @@ -6,7 +6,7 @@ use crate::{ contact_manager::ContactManager, node_manager::NodeManager, pathfinding::PathFindingOutput, - route_stage::RouteStage, + route_stage::{RouteStage, SharedRouteStage}, types::{Date, NodeID}, }; @@ -56,23 +56,14 @@ pub trait Router { /// the first hop. #[cfg_attr(feature = "debug", derive(Debug))] pub struct RoutingOutput { - pub first_hops: HashMap< - usize, - ( - Rc>>, - Vec>>>, - ), - >, + pub first_hops: HashMap>>, Vec>)>, } impl RoutingOutput { pub fn lazy_get_for_unicast( &self, dest: NodeID, - ) -> Option<( - Rc>>, - Rc>>, - )> { + ) -> Option<(Rc>>, SharedRouteStage)> { for (contact, dest_routes) in self.first_hops.values() { for route_rc in dest_routes { if route_rc.borrow().to_node == dest { @@ -119,7 +110,7 @@ pub fn dry_run_multicast( let reached_node = route_borrowed.to_node; - let mut next_routes: HashMap>>, Vec)> = + let mut next_routes: HashMap, Vec)> = HashMap::new(); for dest in downstream_dests { if reached_node == dest { @@ -145,21 +136,14 @@ fn update_multicast( _bundle: &Bundle, at_time: Date, reachable_after_dry_run: Vec, - source_route: Rc>>, + source_route: SharedRouteStage, ) -> RoutingOutput { let mut first_hops_map: HashMap< usize, - ( - Rc>>, - Vec>>>, - ), + (Rc>>, Vec>), > = HashMap::new(); - let mut accumulator: Vec<( - Rc>>, - Option, - Date, - Vec, - )> = vec![(source_route, None, at_time, reachable_after_dry_run)]; + let mut accumulator: Vec<(SharedRouteStage, Option, Date, Vec)> = + vec![(source_route, None, at_time, reachable_after_dry_run)]; #[cfg(not(feature = "node_proc"))] let bundle_to_consider = _bundle; @@ -179,7 +163,7 @@ fn update_multicast( } let reached_node = route_borrowed.to_node; - let mut next_routes: HashMap>>, Vec)> = + let mut next_routes: HashMap, Vec)> = HashMap::new(); for dest in downstream_dests { if reached_node == dest { @@ -248,9 +232,9 @@ fn schedule_multicast( pub fn dry_run_unicast_path( bundle: &Bundle, mut at_time: Date, - source_route: Rc>>, + source_route: SharedRouteStage, with_exclusions: bool, -) -> Option>>> { +) -> Option> { let dest = bundle.destinations[0]; let mut curr_opt = source_route @@ -301,14 +285,14 @@ pub fn dry_run_unicast_path( /// - `node_list`: A list of nodes (`Node`) in the network, used in the pathfinding process. /// /// # Returns -/// Returns an `Option>>>` containing the route stage to the +/// Returns an `Option>` containing the route stage to the /// destination if a valid path is found, or `None` if no path is available. pub fn dry_run_unicast_tree( bundle: &Bundle, at_time: Date, tree: Rc>>, with_exclusions: bool, -) -> Option>>> { +) -> Option> { let dest = bundle.destinations[0]; let tree_ref = tree.borrow(); let dest_route = tree_ref.by_destination.get(dest as usize).cloned()??; @@ -330,7 +314,7 @@ fn update_unicast( _bundle: &Bundle, dest: NodeID, mut at_time: Date, - source_route: Rc>>, + source_route: SharedRouteStage, ) -> RoutingOutput { if source_route.borrow().to_node == dest { panic!("Bundle's destination is equal to source"); @@ -365,10 +349,7 @@ fn update_unicast( if let Some(first) = first_hop { let mut first_hops: HashMap< usize, - ( - Rc>>, - Vec>>>, - ), + (Rc>>, Vec>), > = HashMap::new(); first_hops.insert(first.as_ptr() as usize, (first, vec![curr_route.clone()])); return RoutingOutput { first_hops }; @@ -433,7 +414,7 @@ fn schedule_unicast( fn schedule_unicast_path( bundle: &Bundle, curr_time: Date, - source_route: Rc>>, + source_route: SharedRouteStage, ) -> RoutingOutput { let dest = bundle.destinations[0]; update_unicast(bundle, dest, curr_time, source_route.clone()) diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 960b2a0..d7a02af 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -7,7 +7,7 @@ use crate::{ node_manager::NodeManager, parsing::{DispatchParser, Dispatcher, Lexer, Parser, ParsingState}, pathfinding::Pathfinding, - route_stage::RouteStage, + route_stage::SharedRouteStage, }; pub fn init_pathfinding< @@ -30,7 +30,7 @@ pub fn init_pathfinding< )))) } -pub fn pretty_print(route: Rc>>) { +pub fn pretty_print(route: SharedRouteStage) { let mut backtrace: Vec = Vec::new(); println!( "Route to node {} at t={} with {} hop(s): ", From cc454512f38acc875de687dba965bab6975f3c2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Tchilinguirian?= Date: Fri, 26 Dec 2025 00:06:28 +0100 Subject: [PATCH 06/11] refactor: use StaticMarkerMap where relevant Clippy warned about type complexity where the following, or similar, appears: `Option<&Dispatcher ParsingState>>,` Which raises the warnings. This commit replaces it with: `Option<&StaticMarkerMap>,` This commit defines the following in src/parsing.rs, alongside similar definitions: `pub type StaticMarkerMap<'a, M> = Dispatcher<'a, StaticDispatcher>;` `pub type StaticDispatcher = fn(&mut dyn Lexer) -> ParsingState;` The naming was chosen as similar type definitions exist, but with dyn trait instead of generics. --- examples/bundle_processing/bundle_processing.rs | 6 +++--- .../satellite_constellation/satellite_constellation.rs | 4 ++-- src/contact_plan/from_asabr_lexer.rs | 6 +++--- src/parsing.rs | 7 +++++-- src/utils/mod.rs | 6 +++--- 5 files changed, 16 insertions(+), 13 deletions(-) diff --git a/examples/bundle_processing/bundle_processing.rs b/examples/bundle_processing/bundle_processing.rs index cf56d78..a50271a 100644 --- a/examples/bundle_processing/bundle_processing.rs +++ b/examples/bundle_processing/bundle_processing.rs @@ -4,8 +4,8 @@ use a_sabr::distance::sabr::SABR; use a_sabr::node_manager::none::NoManagement; use a_sabr::node_manager::NodeManager; use a_sabr::parsing::coerce_nm; -use a_sabr::parsing::NodeMarkerMap; -use a_sabr::parsing::{DispatchParser, Dispatcher, Lexer, Parser, ParsingState}; +use a_sabr::parsing::{DispatchParser, Lexer, Parser, ParsingState}; +use a_sabr::parsing::{NodeMarkerMap, StaticMarkerMap}; use a_sabr::pathfinding::hybrid_parenting::HybridParentingPath; use a_sabr::pathfinding::Pathfinding; use a_sabr::types::Date; @@ -93,7 +93,7 @@ impl Parser for Compressing { fn edge_case_example + DispatchParser>( cp_path: &str, bundle_priority: Priority, - node_marker_map: Option<&Dispatcher<'_, fn(&mut dyn Lexer) -> ParsingState>>, + node_marker_map: Option<&StaticMarkerMap>, ) { let bundle = Bundle { source: 0, diff --git a/examples/satellite_constellation/satellite_constellation.rs b/examples/satellite_constellation/satellite_constellation.rs index c736942..d26557d 100644 --- a/examples/satellite_constellation/satellite_constellation.rs +++ b/examples/satellite_constellation/satellite_constellation.rs @@ -5,7 +5,7 @@ use a_sabr::node_manager::none::NoManagement; use a_sabr::node_manager::NodeManager; use a_sabr::parsing::coerce_nm; use a_sabr::parsing::NodeMarkerMap; -use a_sabr::parsing::{DispatchParser, Dispatcher, Lexer, Parser, ParsingState}; +use a_sabr::parsing::{DispatchParser, Lexer, Parser, ParsingState, StaticMarkerMap}; use a_sabr::pathfinding::hybrid_parenting::HybridParentingPath; use a_sabr::pathfinding::Pathfinding; use a_sabr::types::Date; @@ -84,7 +84,7 @@ impl Parser for NoRetention { fn edge_case_example + DispatchParser>( cp_path: &str, - node_marker_map: Option<&Dispatcher<'_, fn(&mut dyn Lexer) -> ParsingState>>, + node_marker_map: Option<&StaticMarkerMap>, ) { let bundle = Bundle { source: 0, diff --git a/src/contact_plan/from_asabr_lexer.rs b/src/contact_plan/from_asabr_lexer.rs index 8d86ede..0333491 100644 --- a/src/contact_plan/from_asabr_lexer.rs +++ b/src/contact_plan/from_asabr_lexer.rs @@ -2,7 +2,7 @@ use crate::{ contact::{Contact, ContactInfo}, contact_manager::ContactManager, node::{Node, NodeInfo}, - parsing::{Dispatcher, Parser}, + parsing::{Parser, StaticMarkerMap}, types::{NodeID, NodeName}, }; use crate::{ @@ -106,8 +106,8 @@ impl ASABRContactPlan { CM: ContactManager + DispatchParser + Parser, >( lexer: &mut dyn Lexer, - node_marker_map: Option<&Dispatcher ParsingState>>, - contact_marker_map: Option<&Dispatcher ParsingState>>, + node_marker_map: Option<&StaticMarkerMap>, + contact_marker_map: Option<&StaticMarkerMap>, ) -> Result<(Vec>, Vec>), String> { let mut contacts: Vec> = Vec::new(); let mut nodes: Vec> = Vec::new(); diff --git a/src/parsing.rs b/src/parsing.rs index 81049a8..782345c 100644 --- a/src/parsing.rs +++ b/src/parsing.rs @@ -7,6 +7,9 @@ pub type NodeMarkerMap<'a> = Dispatcher<'a, NodeDispatcher>; pub type ContactDispatcher = fn(&mut dyn Lexer) -> ParsingState>; pub type NodeDispatcher = fn(&mut dyn Lexer) -> ParsingState>; +pub type StaticMarkerMap<'a, M> = Dispatcher<'a, StaticDispatcher>; +pub type StaticDispatcher = fn(&mut dyn Lexer) -> ParsingState; + /// Wrapper object to a marker -> coercion function map for contacts or nodes versions (T) /// /// # Type Parameters @@ -121,7 +124,7 @@ implement_parser!(ContactManager); /// * `ParsingState<(INFO, MANAGER)>` - The parsing state containing either the parsed components or an error. pub fn parse_components, MANAGER: DispatchParser + Parser>( lexer: &mut dyn Lexer, - dispatch_map: Option<&Dispatcher ParsingState>>, + dispatch_map: Option<&StaticMarkerMap>, ) -> ParsingState<(INFO, MANAGER)> { let info: INFO; let manager: MANAGER; @@ -176,7 +179,7 @@ pub trait DispatchParser> { /// - `EOF` - Indicates the end of the input stream, suggesting that parsing cannot continue. fn parse_dispatch( lexer: &mut dyn Lexer, - _marker_map: Option<&Dispatcher ParsingState>>, + _marker_map: Option<&StaticMarkerMap>, ) -> ParsingState { T::parse(lexer) } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index d7a02af..f6c18a6 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -5,7 +5,7 @@ use crate::{ contact_plan::{asabr_file_lexer::FileLexer, from_asabr_lexer::ASABRContactPlan}, multigraph::Multigraph, node_manager::NodeManager, - parsing::{DispatchParser, Dispatcher, Lexer, Parser, ParsingState}, + parsing::{DispatchParser, Parser, StaticMarkerMap}, pathfinding::Pathfinding, route_stage::SharedRouteStage, }; @@ -16,8 +16,8 @@ pub fn init_pathfinding< P: Pathfinding, >( cp_path: &str, - node_marker_map: Option<&Dispatcher<'_, fn(&mut dyn Lexer) -> ParsingState>>, - contact_marker_map: Option<&Dispatcher<'_, fn(&mut dyn Lexer) -> ParsingState>>, + node_marker_map: Option<&StaticMarkerMap>, + contact_marker_map: Option<&StaticMarkerMap>, ) -> P { let mut mylexer = FileLexer::new(cp_path).unwrap(); let nodes_n_contacts = From 6da50233078a8a9a6b0a2a64069c6ec4423bc1bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Tchilinguirian?= Date: Fri, 26 Dec 2025 02:14:34 +0100 Subject: [PATCH 07/11] docs(routing): fix incorrect doc comment The types in the code did not match those described in that doc comment. This commit attemps to fix this doc comment. --- src/routing/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routing/mod.rs b/src/routing/mod.rs index a53b814..2d62489 100644 --- a/src/routing/mod.rs +++ b/src/routing/mod.rs @@ -52,8 +52,8 @@ pub trait Router { /// to a tuple containing: /// - `Rc>>`: A reference-counted, mutable reference to the `Contact` /// that represents the first hop for the respective route. -/// - `Vec`: A vector of `NodeID`s representing the nodes that can be reached from -/// the first hop. +/// - `Vec>>>`: A vector of reference-counted, mutable +/// references to `RouteStage`s to the nodes that can be reached from the first hop. #[cfg_attr(feature = "debug", derive(Debug))] pub struct RoutingOutput { pub first_hops: HashMap>>, Vec>)>, From 789c305025cb71fccc4302ebfed82046782ec249 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Tchilinguirian?= Date: Fri, 26 Dec 2025 02:02:49 +0100 Subject: [PATCH 08/11] refactor(routing): fix clippy type_complexity Clippy warned about type complexity where the following, or similar, appears: `pub first_hops: HashMap>>, Vec>)>,` Which raises the warnings. This commit reduces it to: `pub first_hops: HashMap>,` By introducing the following *private* types in `src/parsing.rs`, alongside similar definitions: ``` type FirstHopsVec = ( Rc>>, Vec>>>, ); type FirstHop = ( Rc>>, Rc>>, ); ``` The naming was chosen from the naming of attributes that used those types. To not mistake the plural form and to reflect the inner type, its naming ends with 'Vec'. The two new types are private because I did not find a use for them outside the routing module. --- src/routing/mod.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/routing/mod.rs b/src/routing/mod.rs index 2d62489..6e90aa8 100644 --- a/src/routing/mod.rs +++ b/src/routing/mod.rs @@ -15,6 +15,15 @@ pub mod cgr; pub mod spsn; pub mod volcgr; +type FirstHopsVec = ( + Rc>>, + Vec>>>, +); +type FirstHop = ( + Rc>>, + Rc>>, +); + /// A trait to allow generic initialization of routers. pub trait Router { /// Routes a bundle to its destination(s) using either unicast or multicast routing, @@ -49,21 +58,18 @@ pub trait Router { /// # Fields /// /// * `first_hops` - A hashmap mapping from a unique identifier (e.g., an index or destination ID) -/// to a tuple containing: +/// to a `FirstHopsVec` tuple containing: /// - `Rc>>`: A reference-counted, mutable reference to the `Contact` /// that represents the first hop for the respective route. /// - `Vec>>>`: A vector of reference-counted, mutable /// references to `RouteStage`s to the nodes that can be reached from the first hop. #[cfg_attr(feature = "debug", derive(Debug))] pub struct RoutingOutput { - pub first_hops: HashMap>>, Vec>)>, + pub first_hops: HashMap>, } impl RoutingOutput { - pub fn lazy_get_for_unicast( - &self, - dest: NodeID, - ) -> Option<(Rc>>, SharedRouteStage)> { + pub fn lazy_get_for_unicast(&self, dest: NodeID) -> Option> { for (contact, dest_routes) in self.first_hops.values() { for route_rc in dest_routes { if route_rc.borrow().to_node == dest { @@ -138,10 +144,7 @@ fn update_multicast( reachable_after_dry_run: Vec, source_route: SharedRouteStage, ) -> RoutingOutput { - let mut first_hops_map: HashMap< - usize, - (Rc>>, Vec>), - > = HashMap::new(); + let mut first_hops_map: HashMap> = HashMap::new(); let mut accumulator: Vec<(SharedRouteStage, Option, Date, Vec)> = vec![(source_route, None, at_time, reachable_after_dry_run)]; #[cfg(not(feature = "node_proc"))] @@ -347,10 +350,7 @@ fn update_unicast( if curr_route_borrowed.to_node == dest { if let Some(first) = first_hop { - let mut first_hops: HashMap< - usize, - (Rc>>, Vec>), - > = HashMap::new(); + let mut first_hops: HashMap> = HashMap::new(); first_hops.insert(first.as_ptr() as usize, (first, vec![curr_route.clone()])); return RoutingOutput { first_hops }; } From d8bc10debec93e18d6a95c78ab837c2b4ab72036 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Tchilinguirian?= Date: Fri, 26 Dec 2025 02:55:35 +0100 Subject: [PATCH 09/11] refactor(contact_plan): fix clippy type_complexity Clippy warns about the complexity of such types: `Result<(Vec>, Vec>), String>` This commit reduces it to: `Result, String>` By defining a new `ContactPlan` type in `contact_plan/mod.rs`: `type ContactPlan = (Vec>, Vec>);` The name was inspired from `exercises/0-ion-tvgutil-parsing/README.md:104` --- src/contact_plan/from_asabr_lexer.rs | 3 ++- src/contact_plan/from_ion_file.rs | 3 ++- src/contact_plan/from_tvgutil_file.rs | 3 ++- src/contact_plan/mod.rs | 5 +++++ 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/contact_plan/from_asabr_lexer.rs b/src/contact_plan/from_asabr_lexer.rs index 0333491..79503c6 100644 --- a/src/contact_plan/from_asabr_lexer.rs +++ b/src/contact_plan/from_asabr_lexer.rs @@ -1,6 +1,7 @@ use crate::{ contact::{Contact, ContactInfo}, contact_manager::ContactManager, + contact_plan::ContactPlan, node::{Node, NodeInfo}, parsing::{Parser, StaticMarkerMap}, types::{NodeID, NodeName}, @@ -108,7 +109,7 @@ impl ASABRContactPlan { lexer: &mut dyn Lexer, node_marker_map: Option<&StaticMarkerMap>, contact_marker_map: Option<&StaticMarkerMap>, - ) -> Result<(Vec>, Vec>), String> { + ) -> Result, String> { let mut contacts: Vec> = Vec::new(); let mut nodes: Vec> = Vec::new(); diff --git a/src/contact_plan/from_ion_file.rs b/src/contact_plan/from_ion_file.rs index 72b7282..e378fb5 100644 --- a/src/contact_plan/from_ion_file.rs +++ b/src/contact_plan/from_ion_file.rs @@ -9,6 +9,7 @@ use crate::{ seg::{Segment, SegmentationManager}, ContactManager, }, + contact_plan::ContactPlan, node::{Node, NodeInfo}, node_manager::{none::NoManagement, NodeManager}, types::{DataRate, Date, Duration, NodeID}, @@ -163,7 +164,7 @@ fn get_confidence(vec: &[String]) -> f32 { impl IONContactPlan { pub fn parse + ContactManager>( filename: &str, - ) -> io::Result<(Vec>, Vec>)> { + ) -> io::Result> { let file = File::open(filename)?; let mut reader = BufReader::new(file); let mut map_id_map: HashMap = HashMap::new(); diff --git a/src/contact_plan/from_tvgutil_file.rs b/src/contact_plan/from_tvgutil_file.rs index 3d3d44b..f713f0c 100644 --- a/src/contact_plan/from_tvgutil_file.rs +++ b/src/contact_plan/from_tvgutil_file.rs @@ -9,6 +9,7 @@ use crate::{ seg::{Segment, SegmentationManager}, ContactManager, }, + contact_plan::ContactPlan, node::{Node, NodeInfo}, node_manager::{none::NoManagement, NodeManager}, types::{DataRate, Date, Duration, NodeID}, @@ -81,7 +82,7 @@ pub struct TVGUtilContactPlan {} impl TVGUtilContactPlan { pub fn parse + ContactManager>( filename: &str, - ) -> io::Result<(Vec>, Vec>)> { + ) -> io::Result> { let mut nodes: Vec> = Vec::new(); let mut contacts: Vec> = Vec::new(); diff --git a/src/contact_plan/mod.rs b/src/contact_plan/mod.rs index 7b630ec..0fc96f0 100644 --- a/src/contact_plan/mod.rs +++ b/src/contact_plan/mod.rs @@ -1,4 +1,9 @@ +use crate::contact::Contact; +use crate::node::Node; + pub mod asabr_file_lexer; pub mod from_asabr_lexer; pub mod from_ion_file; pub mod from_tvgutil_file; + +type ContactPlan = (Vec>, Vec>); From ce5b8a8cbc37e0d3da6ef79356cd5b3e93869f4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Tchilinguirian?= Date: Fri, 26 Dec 2025 03:06:25 +0100 Subject: [PATCH 10/11] refactor: fix clippy type_complexity This commit introduces a new *public* type: `type SharedPathFindingOutput = Rc>>;` for convenience, and to lower cognitive load where clippy deems necessary. This commit only applies this type in a single place, one where clippy generates a warning. --- src/pathfinding/mod.rs | 2 ++ src/route_storage/mod.rs | 7 ++----- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/pathfinding/mod.rs b/src/pathfinding/mod.rs index ec1eece..8d15187 100644 --- a/src/pathfinding/mod.rs +++ b/src/pathfinding/mod.rs @@ -37,6 +37,8 @@ pub struct PathFindingOutput { pub by_destination: Vec>>, } +pub type SharedPathFindingOutput = Rc>>; + impl PathFindingOutput { /// Creates a new `PathfindingOutput` instance, initializing the `by_destination` vector /// with empty vectors for each destination node and sorting the excluded nodes. diff --git a/src/route_storage/mod.rs b/src/route_storage/mod.rs index f21bfe4..9205606 100644 --- a/src/route_storage/mod.rs +++ b/src/route_storage/mod.rs @@ -8,7 +8,7 @@ use crate::{ contact_manager::ContactManager, multigraph::Multigraph, node_manager::NodeManager, - pathfinding::PathFindingOutput, + pathfinding::{PathFindingOutput, SharedPathFindingOutput}, route_stage::SharedRouteStage, types::{Date, NodeID, Priority, Volume}, }; @@ -37,10 +37,7 @@ pub trait TreeStorage { bundle: &Bundle, curr_time: Date, excluded_nodes_sorted: &[NodeID], - ) -> ( - Option>>>, - Option>, - ); + ) -> (Option>, Option>); /// Stores the pathfinding output tree for future use. /// From 1246f94f531625002d9a6768db18e223e190aaeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Tchilinguirian?= Date: Fri, 26 Dec 2025 00:14:39 +0100 Subject: [PATCH 11/11] style: fix formatting & whitespace --- src/route_storage/mod.rs | 4 ++-- src/routing/mod.rs | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/route_storage/mod.rs b/src/route_storage/mod.rs index 9205606..29acdb4 100644 --- a/src/route_storage/mod.rs +++ b/src/route_storage/mod.rs @@ -57,8 +57,8 @@ impl Route { pub fn from_tree(tree: Rc>>, dest: NodeID) -> Option { let tree_ref = tree.borrow(); let source_stage = tree_ref.get_source_route(); - let destination_stage= tree_ref.by_destination.get(dest as usize).cloned()??; - + let destination_stage = tree_ref.by_destination.get(dest as usize).cloned()??; + Some(Route { source_stage, destination_stage, diff --git a/src/routing/mod.rs b/src/routing/mod.rs index 6e90aa8..9b534d7 100644 --- a/src/routing/mod.rs +++ b/src/routing/mod.rs @@ -190,7 +190,9 @@ fn update_multicast( if let Some(first_hop_contact) = first_hop_contact { let ptr = first_hop_contact.as_ptr() as usize; first_hop_ptr = Some(ptr); - first_hops_map.entry(ptr).or_insert_with(|| (first_hop_contact, Vec::new())); + first_hops_map + .entry(ptr) + .or_insert_with(|| (first_hop_contact, Vec::new())); } } accumulator.push((next_route, first_hop_ptr, time, next_downstream_dests)); @@ -300,7 +302,7 @@ pub fn dry_run_unicast_tree( let tree_ref = tree.borrow(); let dest_route = tree_ref.by_destination.get(dest as usize).cloned()??; let source_route = tree_ref.get_source_route(); - + RouteStage::init_route(dest_route); dry_run_unicast_path(bundle, at_time, source_route, with_exclusions) }