runar_node 0.1.0

Runar Node implementation
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
// Routing Module
//
// This module provides the core routing components for the node's service architecture,
// establishing the message addressing and topic-based communication system. It defines
// how services are addressed, discovered, and how messages are routed between them.
//
// ## Architectural Principles
//
// 1. **Path-based Addressing** - Services are addressed using hierarchical paths
// 2. **Topic-based Communication** - Events use topics for publish-subscribe pattern
// 3. **Separation of Concerns** - Routing is separate from service implementation
// 4. **Deterministic Resolution** - Path resolution follows consistent rules
// 5. **Network Isolation** - Routing respects network boundaries
//
// ## Overview
//
// The routing system is a foundational layer that enables the service architecture
// to function in a decentralized, loosely-coupled manner. It provides:
//
// - **Topic Paths**: Hierarchical addressing for services and events
// - **Wildcard Matching**: Pattern-based subscription and routing
// - **Template Parameters**: Dynamic path segments for flexible routing
// - **Network Isolation**: Multi-network support with proper boundaries
//
// ## Key Concepts
//
// - **Topic Path**: A hierarchical path like `"network:service/action"` or `"service/event"`
// - **Path Segment**: Individual components of a path (literal, wildcard, or template)
// - **Wildcard Matching**: Support for `*` (single segment) and `>` (multi-segment) patterns
// - **Template Parameters**: Dynamic segments like `{user_id}` for flexible routing
//
// ## Examples
//
// ```rust
// use runar_node::routing::TopicPath;
//
// // Create a topic path
// let path = TopicPath::new("math/add", "my-network")?;
//
// // Check if a path matches a pattern
// let pattern = TopicPath::new("math/*", "my-network")?;
// assert!(pattern.matches(&path));
//
// // Use template parameters
// let template = TopicPath::new("users/{user_id}/profile", "my-network")?;
// let params = template.extract_parameters("users/123/profile")?;
// assert_eq!(params.get("user_id"), Some("123"));
// ```

use anyhow::Result;
use std::fmt;
use std::fmt::Debug;
use std::hash::{Hash, Hasher};

/// Type of a path, indicating what kind of resource is being addressed.
///
/// This enum clearly distinguishes between different types of routing targets
/// to ensure proper handling of each type. It enables the system to apply
/// different routing rules and validations based on the path type.
///
/// # Examples
///
/// ```rust
/// use runar_node::routing::PathType;
///
/// let path_type = PathType::Action;
/// match path_type {
///     PathType::Service => {
///         // Handle service discovery and registration
///     }
///     PathType::Action => {
///         // Handle request routing to service actions
///     }
///     PathType::Event => {
///         // Handle event publishing and subscription
///     }
/// }
/// ```
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PathType {
    /// A path to a service - used for service discovery and registration.
    ///
    /// Service paths identify the service itself, not specific actions or events.
    /// Example: `"math"` or `"auth"` for service-level operations.
    Service,

    /// A path to an action on a service - used for request routing.
    ///
    /// Action paths identify specific operations that can be performed on a service.
    /// Example: `"math/add"` or `"auth/login"` for specific actions.
    Action,

    /// A path to an event - used for event routing.
    ///
    /// Event paths identify events that can be published or subscribed to.
    /// Example: `"math/result"` or `"auth/logout"` for event notifications.
    Event,
}

/// Represents a single segment in a path, which can be a literal, wildcard, or template parameter.
///
/// This enum allows paths to include wildcard patterns and template parameters for flexible
/// topic matching in the publish-subscribe system. This enables powerful pattern-based
/// subscriptions and dynamic routing.
///
/// # Examples
///
/// ```rust
/// use runar_node::routing::PathSegment;
///
/// // Literal segments
/// let segment = PathSegment::Literal("math".to_string());
///
/// // Template parameters
/// let segment = PathSegment::Template("user_id".to_string());
///
/// // Wildcards
/// let single = PathSegment::SingleWildcard;  // *
/// let multi = PathSegment::MultiWildcard;   // >
/// ```
///
/// # Wildcard Rules
///
/// - **Single Wildcard (`*`)**: Matches exactly one segment
/// - **Multi Wildcard (`>`)**: Matches one or more segments to the end (must be last)
///
/// # Template Parameters
///
/// Template parameters use `{name}` syntax and can be extracted from matching paths.
/// The braces are stripped when creating the segment for easier access.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PathSegment {
    /// A literal string segment (e.g., "services", "auth", "login").
    ///
    /// Literal segments must match exactly for a path to be considered a match.
    /// They represent fixed components in the path hierarchy.
    Literal(String),

    /// A template parameter segment (e.g., "{service_path}", "{user_id}").
    ///
    /// Template parameters match any segment and store the matched value for later use.
    /// The parameter name is stored without the braces for easier access.
    /// Example: `"{user_id}"` becomes `Template("user_id")`.
    Template(String),

    /// A single-segment wildcard (`*`) - matches any single segment.
    ///
    /// Single wildcards match exactly one path segment. They provide flexibility
    /// while maintaining predictable matching behavior.
    ///
    /// Example: `"services/*/state"` matches `"services/math/state"` but not
    /// `"services/auth/user/state"`.
    SingleWildcard,

    /// A multi-segment wildcard (`>`) - matches one or more segments to the end.
    ///
    /// Multi wildcards match one or more path segments from their position to the
    /// end of the path. They must be the last segment in a pattern.
    ///
    /// Example: `"services/>"` matches `"services/math"`, `"services/auth/login"`, etc.
    ///
    /// **Note**: Multi wildcards must be the last segment in a path pattern.
    MultiWildcard,
}

impl PathSegment {
    /// Parse a string segment into a PathSegment
    ///
    /// INTENTION: Convert raw string segments into the appropriate PathSegment variant,
    /// handling special wildcard characters and template parameters.
    fn from_str(segment: &str) -> Self {
        match segment {
            "*" => Self::SingleWildcard,
            ">" => Self::MultiWildcard,
            s if s.starts_with('{') && s.ends_with('}') => {
                // This is a template parameter - extract the parameter name without braces
                let param_name = &s[1..s.len() - 1];
                Self::Template(param_name.to_string())
            }
            _ => Self::Literal(segment.to_string()),
        }
    }

    /// Check if this segment is a wildcard
    ///
    /// INTENTION: Quickly determine if a segment is a wildcard without pattern matching.
    pub fn is_wildcard(&self) -> bool {
        matches!(self, Self::SingleWildcard | Self::MultiWildcard)
    }

    /// Check if this segment is a multi-segment wildcard
    ///
    /// INTENTION: Identify multi-segment wildcards which have special matching rules.
    pub fn is_multi_wildcard(&self) -> bool {
        matches!(self, Self::MultiWildcard)
    }

    /// Check if this segment is a template parameter
    ///
    /// INTENTION: Quickly determine if a segment is a template parameter.
    pub fn is_template(&self) -> bool {
        matches!(self, Self::Template(_))
    }

    /// Get segment as string slice for display
    ///
    /// INTENTION: Get a string representation without allocating when possible.
    fn _as_str(&self) -> &str {
        match self {
            Self::Literal(s) => s.as_str(),
            // These require allocations - we return slices to the static strings
            Self::SingleWildcard => "*",
            Self::MultiWildcard => ">",
            // Template requires its own allocation in to_string()
            Self::Template(_) => "*", // This is a placeholder that should never be called
        }
    }
}

/// Path representation with network ID and segments, supporting wildcard patterns
///
/// INTENTION: Provide a structured representation of a path string,
/// enabling proper splitting of parts, validation of format, and wildcard matching.
///
/// A TopicPath can be in several formats:
/// - `main:auth/login` (Full path with network_id, service_path, and action)
/// - `auth/login` (Shorthand without network_id, which will be added when TopicPath is created)
/// - `services/*/state` (Pattern with single-segment wildcard)
/// - `events/>` (Pattern with multi-segment wildcard)
impl fmt::Display for PathSegment {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            PathSegment::Literal(s) => f.write_str(s),
            PathSegment::Template(name) => write!(f, "{{{name}}}"),
            PathSegment::SingleWildcard => f.write_str("*"),
            PathSegment::MultiWildcard => f.write_str(">"),
        }
    }
}

#[derive(Debug, Clone)]
pub struct TopicPath {
    /// The raw path string with validated format
    path: String,

    /// The network ID for this path
    network_id: String,

    /// The segments after the network ID
    segments: Vec<PathSegment>,

    /// Whether this path contains wildcard patterns
    is_pattern: bool,

    /// Whether this path contains template parameters
    has_templates: bool,

    /// The service name (first segment of the path) - cached for convenience
    service_path: String,

    /// Cached action path (all segments joined) - computed once at creation time
    cached_action_path: String,

    /// Segment count - cached for quick filtering
    segment_count: usize,

    /// Pre-computed hash components for faster hashing
    hash_components: Vec<u64>,

    /// Bitmap representation of segment types for fast pattern matching
    /// Each 2 bits represent a segment type:
    /// - 00: Literal
    /// - 01: Template
    /// - 10: SingleWildcard
    /// - 11: MultiWildcard
    ///   This allows us to quickly check segment types without iterating through segments
    segment_type_bitmap: u64,
}

// Implement Hash trait for TopicPath to enable use in HashMaps
impl Hash for TopicPath {
    fn hash<H: Hasher>(&self, state: &mut H) {
        // Hash the network ID
        self.network_id.hash(state);

        // Use pre-computed hash components if available
        if !self.hash_components.is_empty() {
            for component in &self.hash_components {
                state.write_u64(*component);
            }
            return;
        }

        // Fallback implementation (should rarely be used)
        for segment in &self.segments {
            match segment {
                PathSegment::Literal(s) => {
                    // Hash type code + string for literal segments
                    0.hash(state);
                    s.hash(state);
                }
                PathSegment::Template(s) => {
                    // Hash type code + parameter name for template segments
                    3.hash(state);
                    s.hash(state);
                }
                PathSegment::SingleWildcard => {
                    // Just hash type code for wildcards
                    1.hash(state);
                }
                PathSegment::MultiWildcard => {
                    // Just hash type code for wildcards
                    2.hash(state);
                }
            }
        }
    }
}

// Implement PartialEq for TopicPath to enable equality comparisons and HashMap lookups
impl PartialEq for TopicPath {
    fn eq(&self, other: &Self) -> bool {
        // Fast path: if paths are identical strings, they're equal
        if self.path == other.path {
            return true;
        }

        // Network IDs must match
        if self.network_id != other.network_id {
            return false;
        }

        // Segment counts must match (now a cached field)
        if self.segment_count != other.segment_count {
            return false;
        }

        // Each segment must match exactly
        for (s1, s2) in self.segments.iter().zip(other.segments.iter()) {
            if s1 != s2 {
                return false;
            }
        }

        true
    }
}

// Implement Eq to confirm TopicPath can be used as HashMap keys
impl Eq for TopicPath {}

// Implement Display for TopicPath for easier use in format strings
impl std::fmt::Display for TopicPath {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.path)
    }
}

impl TopicPath {
    /// Creates a new TopicPath for an action based on this service path
    ///
    /// INTENTION: Provide a simple way to create an action path from a service path,
    /// ensuring consistent formatting and proper path type.
    ///
    /// Example:
    /// ```
    /// use runar_node::TopicPath;
    /// let service_path = TopicPath::new("main:auth", "default").expect("Valid path");
    /// let action_path = service_path.new_action_topic("login").expect("Valid action path");
    ///
    /// assert_eq!(action_path.action_path(), "auth/login");
    /// ```
    pub fn new_action_topic(&self, action_name: &str) -> Result<Self, String> {
        if self.segments.len() > 1 {
            //invalid.. u cannot create an action path on top of another action path
            return Err(
                "Invalid action path - cannot create an action path on top of another action path"
                    .to_string(),
            );
        }

        // Create the full path with the action name
        let full_path_string = format!("{}:{}/{}", self.network_id, self.service_path, action_name);
        TopicPath::new(&full_path_string, &self.network_id)
    }

    /// Creates a new TopicPath for an event based on this service path
    ///
    /// INTENTION: Provide a simple way to create an event path from a service path,
    /// ensuring consistent formatting and proper path type.
    ///
    /// Example:
    /// ```
    /// use runar_node::TopicPath;
    /// let service_path = TopicPath::new("main:auth", "default").expect("Valid path");
    /// let event_path = service_path.new_event_topic("user_logged_in").expect("Valid event path");
    ///
    /// assert_eq!(event_path.action_path(), "auth/user_logged_in");
    /// ```
    pub fn new_event_topic(&self, event_name: &str) -> Result<Self, String> {
        // For now, the format is the same as action_topic, but we'll mark it as an event
        let path = self.new_action_topic(event_name)?;

        // In the future, we might want to distinguish events from actions in the path format
        // For now, we'll just create a path with the event name
        Ok(path)
    }

    pub fn from_full_path(path: &str) -> Result<Self, String> {
        if path.contains(':') {
            // Split at the first colon to separate network_id and path
            let parts: Vec<&str> = path.split(':').collect();
            if parts.len() != 2 {
                return Err(format!(
                    "Invalid path format - should be 'network_id:service_path' received: {path}"
                ));
            }

            // Reject empty network IDs
            if parts[0].is_empty() {
                return Err(format!(
                    "Invalid path format - network ID cannot be empty received: {path}"
                ));
            }

            let network_id = parts[0];
            let path_without_network = parts[1];
            Self::new(path_without_network, network_id)
        } else {
            Err(format!(
                "Invalid path format - missing network_id received: {path}"
            ))
        }
    }

    /// Create a new TopicPath from a string
    ///
    /// INTENTION: Validate and construct a TopicPath from a string input,
    /// ensuring it follows the required format conventions.
    ///
    /// This method now supports wildcard patterns:
    /// - "*" matches any single segment
    /// - ">" matches one or more segments to the end (must be the last segment)
    ///
    /// Example:
    /// ```
    /// use runar_node::routing::TopicPath;
    ///
    /// // With network_id prefix
    /// let path = TopicPath::new("main:auth/login", "default").expect("Valid path");
    /// assert_eq!(path.network_id(), "main");
    /// assert_eq!(path.service_path(), "auth");
    /// assert_eq!(path.action_path(), "auth/login");
    ///
    /// // With wildcards
    /// let pattern = TopicPath::new("main:services/*/state", "default").expect("Valid pattern");
    /// assert!(pattern.is_pattern());
    /// ```
    pub fn new(path: &str, default_network: &str) -> Result<Self, String> {
        // Parse the network ID and path parts
        let (network_id, path_without_network) = if path.contains(':') {
            // Split at the first colon to separate network_id and path
            let parts: Vec<&str> = path.split(':').collect();
            if parts.len() != 2 {
                return Err(format!("Invalid path format - should be 'network_id:service_path' or 'service_path': {path}"));
            }

            // Reject empty network IDs
            if parts[0].is_empty() {
                return Err(format!("Network ID cannot be empty: {path}"));
            }

            (parts[0], parts[1])
        } else {
            // No network_id prefix, use the default
            (default_network, path)
        };

        // Split the path into segments
        let path_segments: Vec<&str> = path_without_network
            .split('/')
            .filter(|s| !s.is_empty())
            .collect();

        // Paths must have at least one segment (the service name)
        if path_segments.is_empty() {
            return Err(format!(
                "Invalid path - must have at least one segment: {path}"
            ));
        }

        // Process each segment
        let mut segments = Vec::with_capacity(path_segments.len());
        let mut is_pattern = false;
        let mut has_templates = false;
        let mut _multi_wildcard_found = false;
        let mut hash_components = Vec::with_capacity(path_segments.len());
        let mut segment_type_bitmap: u64 = 0;

        for (i, segment_str) in path_segments.iter().enumerate() {
            let segment = PathSegment::from_str(segment_str);

            // Check for pattern and validate multi-wildcards
            match &segment {
                PathSegment::SingleWildcard => {
                    is_pattern = true;
                    Self::set_segment_type(
                        &mut segment_type_bitmap,
                        i,
                        Self::SEGMENT_TYPE_SINGLE_WILDCARD,
                    );
                }
                PathSegment::MultiWildcard => {
                    is_pattern = true;
                    _multi_wildcard_found = true;

                    // Ensure multi-wildcard is the last segment
                    if i < path_segments.len() - 1 {
                        return Err(
                            "Multi-segment wildcard (>) must be the last segment in a path"
                                .to_string(),
                        );
                    }

                    Self::set_segment_type(
                        &mut segment_type_bitmap,
                        i,
                        Self::SEGMENT_TYPE_MULTI_WILDCARD,
                    );
                }
                PathSegment::Template(_) => {
                    has_templates = true;
                    Self::set_segment_type(
                        &mut segment_type_bitmap,
                        i,
                        Self::SEGMENT_TYPE_TEMPLATE,
                    );
                }
                PathSegment::Literal(_) => {
                    Self::set_segment_type(&mut segment_type_bitmap, i, Self::SEGMENT_TYPE_LITERAL);
                }
            }

            // Compute hash component for this segment
            let mut segment_hasher = std::collections::hash_map::DefaultHasher::new();
            match &segment {
                PathSegment::Literal(s) => {
                    0.hash(&mut segment_hasher);
                    s.hash(&mut segment_hasher);
                }
                PathSegment::Template(s) => {
                    3.hash(&mut segment_hasher);
                    s.hash(&mut segment_hasher);
                }
                PathSegment::SingleWildcard => {
                    1.hash(&mut segment_hasher);
                }
                PathSegment::MultiWildcard => {
                    2.hash(&mut segment_hasher);
                }
            }
            hash_components.push(segment_hasher.finish());

            segments.push(segment);
        }

        // Save the service path (first segment) for easy access
        let service_path = match &segments[0] {
            PathSegment::Literal(s) => s.clone(),
            PathSegment::Template(s) => format!("{{{s}}}"),
            PathSegment::SingleWildcard => "*".to_string(),
            PathSegment::MultiWildcard => ">".to_string(),
        };

        // Create the full path string (for display/serialization)
        let full_path_str = format!("{network_id}:{path_without_network}");

        // Pre-compute the action path for caching
        let cached_action_path = if segments.len() <= 1 {
            "".to_string()
        } else {
            segments
                .iter()
                .map(|segment| segment.to_string())
                .collect::<Vec<String>>()
                .join("/")
        };

        let result = Self {
            path: full_path_str,
            network_id: network_id.to_string(),
            segment_count: segments.len(),
            segments,
            is_pattern,
            has_templates,
            service_path,
            cached_action_path,
            hash_components,
            segment_type_bitmap,
        };

        Ok(result)
    }

    /// Check if this path contains wildcards
    ///
    /// INTENTION: Quickly determine if a path is a wildcard pattern,
    /// which affects how it's used for matching.
    pub fn is_pattern(&self) -> bool {
        self.is_pattern
    }

    /// Check if this path contains a multi-segment wildcard
    ///
    /// INTENTION: Identify paths with multi-segment wildcards which have
    /// special matching rules and storage requirements.
    pub fn has_multi_wildcard(&self) -> bool {
        // Check if any segment is a multi-wildcard
        for i in 0..self.segment_count {
            if self.has_segment_type(i, Self::SEGMENT_TYPE_MULTI_WILDCARD) {
                return true;
            }
        }

        false
    }

    /// Get the path after the network ID
    ///
    /// INTENTION: Get the complete path after the network ID, including
    /// all segments. This is useful when you need the path for routing.
    ///
    /// Example:
    /// ```
    /// use runar_node::routing::TopicPath;
    ///
    /// let path = TopicPath::new("main:auth/login", "default").expect("Valid path");
    /// assert_eq!(path.action_path(), "auth/login");
    ///
    /// // When there is only a service with no action, returns empty string
    /// let service_only = TopicPath::new("main:auth", "default").expect("Valid path");
    /// assert_eq!(service_only.action_path(), "");
    /// ```
    pub fn action_path(&self) -> String {
        self.cached_action_path.clone()
    }

    /// Get the path as a string
    ///
    /// INTENTION: Access the raw path string for this TopicPath,
    /// useful for display and logging purposes.
    pub fn as_str(&self) -> &str {
        &self.path
    }

    /// Get the network ID from this path
    ///
    /// INTENTION: Extract just the network segment from the path,
    /// which is crucial for network isolation and routing.
    ///
    /// Example:
    /// ```
    /// use runar_node::routing::TopicPath;
    ///
    /// let path = TopicPath::new("main:auth/login", "default").expect("Valid path");
    /// assert_eq!(path.network_id(), "main");
    /// ```
    pub fn network_id(&self) -> String {
        self.network_id.clone()
    }

    /// Get the service path part of this path
    ///
    /// INTENTION: Extract the service path from the full path,
    /// which is used for service lookup and addressing.
    ///
    /// Example:
    /// ```
    /// use runar_node::routing::TopicPath;
    ///
    /// let path = TopicPath::new("main:auth/login", "default").expect("Valid path");
    /// // The service_path method returns just the service name (first segment)
    /// assert_eq!(path.service_path(), "auth");
    ///
    /// // If you need just the first segment, use get_segments
    /// let segments = path.get_segments();
    /// assert_eq!(segments[0], "auth");
    /// ```
    pub fn service_path(&self) -> String {
        self.service_path.clone()
    }

    /// Create a new service path from a network ID and service name
    ///
    /// INTENTION: Create a TopicPath specifically for a service,
    /// avoiding manual string concatenation and validation.
    ///
    /// Example:
    /// ```
    /// use runar_node::routing::TopicPath;
    ///
    /// let path = TopicPath::new_service("main", "auth");
    /// assert_eq!(path.as_str(), "main:auth");
    /// ```
    pub fn new_service(network_id: &str, service_name: &str) -> Self {
        let network_id_string = network_id.to_string();
        let service_name_string = service_name.to_string();

        let path = format!("{network_id_string}:{service_name_string}");
        Self {
            path,
            network_id: network_id_string,
            service_path: service_name_string.clone(),
            segments: vec![PathSegment::Literal(service_name_string)],
            is_pattern: false,
            has_templates: false,
            cached_action_path: "".to_string(),
            segment_count: 1,
            hash_components: Vec::new(),
            segment_type_bitmap: 0,
        }
    }

    /// Check if this path starts with another path
    ///
    /// INTENTION: Determine if this path is a "child" or more specific
    /// version of another path, useful for hierarchical routing and
    /// subscription matching.
    ///
    /// Example:
    /// ```
    /// use runar_node::routing::TopicPath;
    ///
    /// let path = TopicPath::new("main:auth/users", "default").expect("Valid path");
    /// let prefix = TopicPath::new("main:auth", "default").expect("Valid path");
    /// let different = TopicPath::new("main:payments", "default").expect("Valid path");
    ///
    /// assert!(path.starts_with(&prefix));
    /// assert!(!path.starts_with(&different));
    /// ```
    pub fn starts_with(&self, other: &TopicPath) -> bool {
        self.network_id == other.network_id && self.service_path.starts_with(&other.service_path)
    }

    /// Create a child path by appending a segment
    ///
    /// INTENTION: Generate a new TopicPath that is a child of this path,
    /// useful for creating more specific paths from a base path.
    ///
    /// Example:
    /// ```
    /// use runar_node::routing::TopicPath;
    ///
    /// let base = TopicPath::new("main:auth", "default").expect("Valid path");
    /// let child = base.child("login").expect("Valid child path");
    ///
    /// assert_eq!(child.as_str(), "main:auth/login");
    /// ```
    pub fn child(&self, segment: &str) -> Result<Self, String> {
        // Ensure segment doesn't contain slashes
        if segment.contains('/') {
            return Err(format!("Child segment cannot contain slashes: {segment}"));
        }

        // Create the new path string
        let new_path_str = if self.cached_action_path.is_empty() {
            // For service-only paths, new path should include service path + new segment
            format!("{}/{}", self.service_path, segment)
        } else {
            format!("{}/{}", self.cached_action_path, segment)
        };

        // Create a full path with network ID
        let full_path_str = format!("{}:{}", self.network_id, new_path_str);

        // Create a new set of segments based on the current segments plus the new one
        let mut new_segments = self.segments.clone();
        let new_segment = PathSegment::from_str(segment);

        // Check if this path is a pattern (has wildcards)
        let is_pattern = self.is_pattern
            || matches!(
                new_segment,
                PathSegment::SingleWildcard | PathSegment::MultiWildcard
            );

        // Check if this path has templates
        let has_templates = self.has_templates || matches!(new_segment, PathSegment::Template(_));

        // Add new segment to bitmap
        let mut segment_type_bitmap = self.segment_type_bitmap;
        match &new_segment {
            PathSegment::Literal(_) => {
                Self::set_segment_type(
                    &mut segment_type_bitmap,
                    self.segment_count,
                    Self::SEGMENT_TYPE_LITERAL,
                );
            }
            PathSegment::Template(_) => {
                Self::set_segment_type(
                    &mut segment_type_bitmap,
                    self.segment_count,
                    Self::SEGMENT_TYPE_TEMPLATE,
                );
            }
            PathSegment::SingleWildcard => {
                Self::set_segment_type(
                    &mut segment_type_bitmap,
                    self.segment_count,
                    Self::SEGMENT_TYPE_SINGLE_WILDCARD,
                );
            }
            PathSegment::MultiWildcard => {
                Self::set_segment_type(
                    &mut segment_type_bitmap,
                    self.segment_count,
                    Self::SEGMENT_TYPE_MULTI_WILDCARD,
                );
            }
        }

        new_segments.push(new_segment);

        Ok(Self {
            path: full_path_str,
            network_id: self.network_id.clone(),
            segment_count: self.segment_count + 1,
            segments: new_segments,
            is_pattern,
            has_templates,
            service_path: self.service_path.clone(),
            cached_action_path: new_path_str,
            hash_components: Vec::new(), // Recompute later if needed
            segment_type_bitmap,
        })
    }

    /// Get the path segments
    ///
    /// INTENTION: Get the segments of the path after the network ID.
    /// This is useful for path analysis and custom path parsing.
    ///
    /// Example:
    /// ```
    /// use runar_node::routing::TopicPath;
    ///
    /// let path = TopicPath::new("main:auth/login/form", "default").expect("Valid path");
    /// let segments = path.get_segments();
    /// assert_eq!(segments, vec!["auth", "login", "form"]);
    /// ```
    pub fn get_segments(&self) -> Vec<String> {
        self.segments
            .iter()
            .map(|segment| segment.to_string())
            .collect()
    }

    /// Create a parent path
    ///
    /// INTENTION: Generate a new TopicPath that is the parent of this path,
    /// useful for navigating up the path hierarchy.
    ///
    /// Example:
    /// ```
    /// use runar_node::routing::TopicPath;
    ///
    /// let path = TopicPath::new("main:auth/users", "default").expect("Valid path");
    /// let parent = path.parent().expect("Valid parent path");
    ///
    /// assert_eq!(parent.as_str(), "main:auth");
    /// ```
    pub fn parent(&self) -> Result<Self, String> {
        if self.segments.len() <= 1 {
            return Err("Cannot get parent of root or service-only path".to_string());
        }

        // Create a new set of segments without the last segment
        let parent_segments = self.segments[0..self.segments.len() - 1].to_vec();

        // Reconstruct the path string from segments
        let path_str = parent_segments
            .iter()
            .map(|segment| segment.to_string())
            .collect::<Vec<String>>()
            .join("/");

        // Create the full path with network ID
        let full_path = format!("{}:{}", self.network_id, path_str);

        // Check if parent is a pattern
        let mut is_pattern = false;
        let mut has_templates = false;

        // Create new bitmap by removing the last 2 bits
        let mut segment_type_bitmap = self.segment_type_bitmap;
        segment_type_bitmap &= !(0b11 << ((self.segment_count - 1) * 2));

        // Check each segment in the parent for patterns
        for i in 0..parent_segments.len() {
            let segment_type = Self::get_segment_type(segment_type_bitmap, i);
            match segment_type {
                Self::SEGMENT_TYPE_SINGLE_WILDCARD | Self::SEGMENT_TYPE_MULTI_WILDCARD => {
                    is_pattern = true;
                }
                Self::SEGMENT_TYPE_TEMPLATE => {
                    has_templates = true;
                }
                _ => {}
            }
        }

        Ok(Self {
            path: full_path,
            network_id: self.network_id.clone(),
            segment_count: self.segment_count - 1,
            segments: parent_segments,
            is_pattern,
            has_templates,
            service_path: self.service_path.clone(),
            cached_action_path: path_str,
            hash_components: Vec::new(), // Recompute later if needed
            segment_type_bitmap,
        })
    }

    /// Create a default path for running unit tests with default network ID
    ///
    /// INTENTION: Simplify test setup by creating a valid path with a default network ID.
    ///
    /// Note: This is primarily intended for testing purposes.
    ///
    /// Example:
    /// ```
    /// use runar_node::routing::TopicPath;
    ///
    /// let path = TopicPath::test_default("auth/login");
    /// assert_eq!(path.as_str(), "default:auth/login");
    /// ```
    pub fn test_default(path: &str) -> Self {
        Self::new(path, "default").unwrap()
    }

    /// Match this path against a template pattern and extract parameters
    ///
    /// INTENTION: Enable services to define URL-like templates with named parameters
    /// and extract those parameter values from actual request paths.
    ///
    /// Template patterns can include segments like `{param_name}` which will match
    /// any value in that position and capture it with the specified name.
    ///
    /// Example:
    /// ```
    /// use runar_node::routing::TopicPath;
    ///
    /// let template = "services/{service_path}/state";
    /// let path = TopicPath::new("main:services/math/state", "main").expect("Valid path");
    ///
    /// let params = path.extract_params(template).expect("Template should match");
    /// assert_eq!(params.get("service_path"), Some(&"math".to_string()));
    ///
    /// // Non-matching templates return an error
    /// let non_matching = TopicPath::new("main:users/profile", "main").expect("Valid path");
    /// assert!(non_matching.extract_params(template).is_err());
    /// ```
    pub fn extract_params(
        &self,
        template: &str,
    ) -> Result<std::collections::HashMap<String, String>, String> {
        let mut params = std::collections::HashMap::new();

        // Get segments from the actual path (excluding network_id)
        let path_segments = self.get_segments();

        // Get segments from the template
        let template_segments: Vec<&str> = template.split('/').filter(|s| !s.is_empty()).collect();

        // If segment counts don't match, the template doesn't apply
        if path_segments.len() != template_segments.len() {
            return Err(format!(
                "Path segment count ({}) doesn't match template segment count ({})",
                path_segments.len(),
                template_segments.len()
            ));
        }

        // Match each segment and extract parameters
        for (i, template_segment) in template_segments.iter().enumerate() {
            if template_segment.starts_with('{') && template_segment.ends_with('}') {
                // This is a parameter segment - extract the parameter name
                let param_name = template_segment[1..template_segment.len() - 1].to_string();
                // Store the actual value from the path
                params.insert(param_name, path_segments[i].clone());
            } else if template_segment != &path_segments[i] {
                // This is a literal segment and it doesn't match
                return Err(format!(
                    "Path segment '{}' doesn't match template segment '{}'",
                    path_segments[i], template_segment
                ));
            }
            // If it's a literal and matches, continue to next segment
        }

        Ok(params)
    }

    /// Check if a path matches a template pattern
    ///
    /// INTENTION: Quickly determine if a path can be processed by a particular
    /// template, without needing to extract parameters.
    ///
    /// Example:
    /// ```
    /// use runar_node::routing::TopicPath;
    ///
    /// let template = "services/{service_path}/state";
    /// let path = TopicPath::new("main:services/math/state", "default").expect("Valid path");
    ///
    /// assert!(path.matches_template(template));
    ///
    /// let non_matching = TopicPath::new("main:users/profile", "default").expect("Valid path");
    /// assert!(!non_matching.matches_template(template));
    /// ```
    pub fn matches_template(&self, template: &str) -> bool {
        // Fast path: if neither has templates, do simple comparison
        if !self.has_templates && !template.contains('{') {
            return self.path.contains(template);
        }

        // Use faster matching for common template patterns
        let template_segments: Vec<&str> = template.split('/').filter(|s| !s.is_empty()).collect();

        // Quickly check segment counts to avoid unnecessary processing
        if template_segments.len() != self.segment_count {
            return false;
        }

        // Iterate segments to check template compatibility
        let path_segments = self.get_segments();

        for (i, template_segment) in template_segments.iter().enumerate() {
            if template_segment.starts_with('{') && template_segment.ends_with('}') {
                // Template parameter segment - matches any literal in corresponding position
                continue;
            } else if template_segment != &path_segments[i] {
                // Literal segment must match exactly
                return false;
            }
        }

        true
    }

    /// Check if this path contains template parameters
    ///
    /// INTENTION: Quickly determine if a path has template parameters,
    /// which affects template matching behavior.
    pub fn has_templates(&self) -> bool {
        self.has_templates
    }

    /// Get the number of segments in this path
    ///
    /// INTENTION: Quickly get the segment count without iterating segments.
    pub fn segment_count(&self) -> usize {
        self.segment_count
    }

    // Helper methods for bitmap operations
    fn set_segment_type(bitmap: &mut u64, index: usize, segment_type: u8) {
        // Each segment uses 2 bits
        let shift = index * 2;
        // Clear the existing bits for this segment
        *bitmap &= !(0b11 << shift);
        // Set the new segment type
        *bitmap |= (segment_type as u64) << shift;
    }

    fn get_segment_type(bitmap: u64, index: usize) -> u8 {
        // Extract 2 bits representing the segment type
        ((bitmap >> (index * 2)) & 0b11) as u8
    }

    // Constants for segment types
    const SEGMENT_TYPE_LITERAL: u8 = 0b00;
    const SEGMENT_TYPE_TEMPLATE: u8 = 0b01;
    const SEGMENT_TYPE_SINGLE_WILDCARD: u8 = 0b10;
    const SEGMENT_TYPE_MULTI_WILDCARD: u8 = 0b11;

    // Use bitmap for faster segment type checking
    pub fn has_segment_type(&self, index: usize, segment_type: u8) -> bool {
        if index >= self.segment_count {
            return false;
        }

        Self::get_segment_type(self.segment_type_bitmap, index) == segment_type
    }

    /// Implement pattern matching against another path
    ///
    /// INTENTION: Allow checking if a topic matches a pattern with wildcards,
    /// enabling powerful pattern-based subscriptions.
    ///
    /// Example:
    /// ```
    /// use runar_node::routing::TopicPath;
    ///
    /// let pattern = TopicPath::new("main:services/*/state", "default").expect("Valid pattern");
    /// let topic1 = TopicPath::new("main:services/math/state", "default").expect("Valid topic");
    /// let topic2 = TopicPath::new("main:services/math/config", "default").expect("Valid topic");
    ///
    /// assert!(pattern.matches(&topic1));
    /// assert!(!pattern.matches(&topic2));
    /// ```
    pub fn matches(&self, topic: &TopicPath) -> bool {
        // Network ID must match
        if self.network_id != topic.network_id {
            return false;
        }

        // Fast path 1: if paths are identical strings, they're equal
        if self.path == topic.path {
            return true;
        }

        // Fast path 2: if segment counts don't match and there's no multi-wildcard,
        // the paths can't match
        if self.segment_count != topic.segment_count && !self.has_multi_wildcard() {
            return false;
        }

        // Fast path 3: If neither path is a pattern, and they're not identical strings,
        // they can't match
        if !self.is_pattern && !topic.is_pattern && !self.has_templates && !topic.has_templates {
            return false;
        }

        // Check for template path matching concrete path special case
        if self.has_templates && !topic.has_templates {
            // A template path doesn't match a concrete path in this direction
            // For example: "services/{service_path}" doesn't match "services/math"
            // But "services/math" does match "services/{service_path}"
            return false;
        }

        // Check for reverse template matching - concrete path matching template path
        if !self.has_templates && topic.has_templates {
            // A concrete path can match a template path
            // For example: "services/math" matches "services/{service_path}"
            // Verify by checking if the concrete path would extract valid parameters from the template
            return topic.matches_template(&self.action_path());
        }

        // Otherwise, perform segment-by-segment matching
        self.segments_match(&self.segments, &topic.segments)
    }

    // Optimized segment matching with improved template handling
    fn segments_match(
        &self,
        pattern_segments: &[PathSegment],
        topic_segments: &[PathSegment],
    ) -> bool {
        // Special case: multi-wildcard at the end
        if let Some(PathSegment::MultiWildcard) = pattern_segments.last() {
            // If pattern ends with >, topic must have at least as many segments as pattern minus 1
            if topic_segments.len() < pattern_segments.len() - 1 {
                return false;
            }

            // Check all segments before the multi-wildcard
            for i in 0..pattern_segments.len() - 1 {
                match &pattern_segments[i] {
                    PathSegment::Literal(p) => {
                        // For literals, the segments must match exactly
                        match &topic_segments[i] {
                            PathSegment::Literal(t) if p == t => continue,
                            _ => return false,
                        }
                    }
                    PathSegment::Template(_) => {
                        // Template parameters match any literal segment
                        match &topic_segments[i] {
                            PathSegment::Literal(_) => continue,
                            _ => return false,
                        }
                    }
                    PathSegment::SingleWildcard => {
                        // For single wildcards, any segment matches
                        continue;
                    }
                    PathSegment::MultiWildcard => {
                        // Should not happen, as we're iterating up to len-1
                        unreachable!("Multi-wildcard found before the end of pattern");
                    }
                }
            }

            // If we get here, all segments matched
            return true;
        }

        // If pattern doesn't end with multi-wildcard, segment counts must match
        if pattern_segments.len() != topic_segments.len() {
            return false;
        }

        // Check each segment - fast path for literal matches
        for (i, p) in pattern_segments.iter().enumerate() {
            let t = &topic_segments[i];

            // Fast path for identical segments
            if p == t {
                continue;
            }

            match p {
                PathSegment::Literal(_) => {
                    // Literals must match exactly, but we already checked
                    // p == t above, so if we get here they don't match
                    return false;
                }
                PathSegment::Template(_) => {
                    // Template parameters match any literal segment
                    match t {
                        PathSegment::Literal(_) => continue,
                        _ => return false,
                    }
                }
                PathSegment::SingleWildcard => {
                    // Single wildcards match any segment
                    continue;
                }
                PathSegment::MultiWildcard => {
                    // Multi-wildcards should only appear at the end
                    // This is a defensive check - should never happen due to parsing
                    return false;
                }
            }
        }

        // If we get here, all segments matched
        true
    }

    /// Create a TopicPath from a template and parameter values
    ///
    /// INTENTION: Allow dynamic construction of TopicPaths from templates with
    /// parameter placeholders, similar to route templates in web frameworks.
    ///
    /// Example:
    /// ```
    /// use runar_node::routing::TopicPath;
    /// use std::collections::HashMap;
    ///
    /// let mut params = HashMap::new();
    /// params.insert("service_path".to_string(), "math".to_string());
    /// params.insert("action".to_string(), "add".to_string());
    ///
    /// let path = TopicPath::from_template(
    ///     "services/{service_path}/{action}",
    ///     params,
    ///     "main"
    /// ).expect("Valid template");
    ///
    /// assert_eq!(path.as_str(), "main:services/math/add");
    /// ```
    pub fn from_template(
        template_string: &str,
        params: std::collections::HashMap<String, String>,
        network_id_string: &str,
    ) -> Result<Self, String> {
        // Get segments from the template
        let template_segments: Vec<&str> = template_string
            .split('/')
            .filter(|s| !s.is_empty())
            .collect();

        let mut path_segments = Vec::new();

        // Process each template segment
        for template_segment in template_segments.iter() {
            if template_segment.starts_with('{') && template_segment.ends_with('}') {
                // This is a parameter segment - extract the parameter name
                let param_name = &template_segment[1..template_segment.len() - 1];

                // Look up the parameter value
                match params.get(param_name) {
                    Some(value) => path_segments.push(PathSegment::Literal(value.clone())),
                    None => return Err(format!("Missing parameter value for '{param_name}'")),
                }
            } else {
                // This is a literal segment
                path_segments.push(PathSegment::Literal(template_segment.to_string()));
            }
        }
        // Construct the final path
        let path_str = path_segments
            .iter()
            .map(|segment| segment.to_string())
            .collect::<Vec<String>>()
            .join("/");
        Self::new(path_str.as_str(), network_id_string)
    }
}

// Export the PathTrie module
mod path_registry;
pub use path_registry::PathTrie;
pub use path_registry::PathTrieMatch;