bronzite_types/
lib.rs

1//! Shared types for Bronzite IPC protocol.
2//!
3//! This crate defines the query and response types used for communication
4//! between proc-macros (clients) and the Bronzite daemon.
5
6use std::collections::HashMap;
7
8use serde::{Deserialize, Serialize};
9
10// ============================================================================
11// Requests and Responses
12// ============================================================================
13
14/// A request sent from a client to the Bronzite daemon.
15#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct Request {
17    /// Unique request ID for correlating responses
18    pub id: u64,
19    /// The crate being queried (e.g., "my_crate")
20    pub crate_name: String,
21    /// The query to execute
22    pub query: Query,
23}
24
25/// Available queries for type system introspection.
26#[derive(Debug, Clone, Serialize, Deserialize)]
27#[serde(tag = "type", rename_all = "snake_case")]
28pub enum Query {
29    /// List all items in the crate
30    ListItems,
31
32    /// Get detailed information about a specific type
33    GetType { path: String },
34
35    /// Get all trait implementations for a type
36    GetTraitImpls { type_path: String },
37
38    /// Get inherent impl blocks for a type (impl Foo { ... })
39    GetInherentImpls { type_path: String },
40
41    /// Get all fields of a struct or enum variant
42    GetFields { type_path: String },
43
44    /// Get memory layout information for a type
45    GetLayout { type_path: String },
46
47    /// Get all traits defined in the crate
48    GetTraits,
49
50    /// Get detailed information about a trait
51    GetTrait { path: String },
52
53    /// Find types matching a path pattern (e.g., "bevy::prelude::*")
54    FindTypes { pattern: String },
55
56    /// Resolve a type alias to its underlying type
57    ResolveAlias { path: String },
58
59    /// Check if a type implements a trait
60    CheckImpl {
61        type_path: String,
62        trait_path: String,
63    },
64
65    /// Get all types that implement a specific trait
66    GetImplementors { trait_path: String },
67
68    /// Ping to check if daemon is alive
69    Ping,
70
71    /// Request the daemon to shut down
72    Shutdown,
73}
74
75/// A response from the Bronzite daemon.
76#[derive(Debug, Clone, Serialize, Deserialize)]
77pub struct Response {
78    /// The request ID this response corresponds to
79    pub id: u64,
80    /// The result of the query
81    pub result: QueryResult,
82}
83
84/// The result of a query execution.
85#[derive(Debug, Clone, Serialize, Deserialize)]
86#[serde(tag = "status", rename_all = "snake_case")]
87pub enum QueryResult {
88    /// Query executed successfully
89    Success { data: QueryData },
90    /// Query failed with an error
91    Error { message: String },
92}
93
94/// Data returned from successful queries.
95#[derive(Debug, Clone, Serialize, Deserialize)]
96#[serde(tag = "type", rename_all = "snake_case")]
97pub enum QueryData {
98    /// Response to ListItems
99    Items { items: Vec<ItemInfo> },
100
101    /// Response to GetType
102    TypeInfo(TypeDetails),
103
104    /// Response to GetTraitImpls
105    TraitImpls { impls: Vec<TraitImplDetails> },
106
107    /// Response to GetInherentImpls
108    InherentImpls { impls: Vec<InherentImplDetails> },
109
110    /// Response to GetFields
111    Fields { fields: Vec<FieldInfo> },
112
113    /// Response to GetLayout
114    Layout(LayoutInfo),
115
116    /// Response to GetTraits
117    Traits { traits: Vec<TraitInfo> },
118
119    /// Response to GetTrait
120    TraitDetails(TraitDetails),
121
122    /// Response to FindTypes
123    Types { types: Vec<TypeSummary> },
124
125    /// Response to ResolveAlias
126    ResolvedType {
127        original: String,
128        resolved: String,
129        chain: Vec<String>,
130    },
131
132    /// Response to CheckImpl
133    ImplCheck {
134        implements: bool,
135        impl_info: Option<TraitImplDetails>,
136    },
137
138    /// Response to GetImplementors
139    Implementors { types: Vec<TypeSummary> },
140
141    /// Response to Ping
142    Pong,
143
144    /// Response to Shutdown
145    ShuttingDown,
146}
147
148// ============================================================================
149// Item Information
150// ============================================================================
151
152/// Basic information about an item in the crate.
153#[derive(Debug, Clone, Serialize, Deserialize)]
154pub struct ItemInfo {
155    /// The item's name
156    pub name: String,
157    /// The full path to the item
158    pub path: String,
159    /// What kind of item this is
160    pub kind: ItemKind,
161    /// Visibility of the item
162    pub visibility: Visibility,
163    /// Span information (file, line, column)
164    pub span: Option<SpanInfo>,
165}
166
167/// The kind of an item.
168#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
169#[serde(rename_all = "snake_case")]
170pub enum ItemKind {
171    Struct,
172    Enum,
173    Union,
174    Trait,
175    Function,
176    Const,
177    Static,
178    TypeAlias,
179    Impl,
180    Mod,
181    Use,
182    ExternCrate,
183    Macro,
184    TraitAlias,
185    Other(String),
186}
187
188/// Visibility of an item.
189#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
190#[serde(rename_all = "snake_case")]
191pub enum Visibility {
192    Public,
193    Crate,
194    Restricted { path: String },
195    Private,
196}
197
198/// Source location information.
199#[derive(Debug, Clone, Serialize, Deserialize)]
200pub struct SpanInfo {
201    pub file: String,
202    pub start_line: u32,
203    pub start_col: u32,
204    pub end_line: u32,
205    pub end_col: u32,
206}
207
208// ============================================================================
209// Type Information
210// ============================================================================
211
212/// Summary information about a type (for listings).
213#[derive(Debug, Clone, Serialize, Deserialize)]
214pub struct TypeSummary {
215    pub name: String,
216    pub path: String,
217    pub kind: TypeKind,
218    pub generics: Vec<GenericParam>,
219}
220
221/// Detailed information about a type.
222#[derive(Debug, Clone, Serialize, Deserialize)]
223pub struct TypeDetails {
224    pub name: String,
225    pub path: String,
226    pub kind: TypeKind,
227    pub visibility: Visibility,
228    pub generics: Vec<GenericParam>,
229    pub where_clause: Option<String>,
230    /// Doc comments
231    pub docs: Option<String>,
232    /// Attributes (as strings)
233    pub attributes: Vec<String>,
234    /// For structs: fields
235    pub fields: Option<Vec<FieldInfo>>,
236    /// For enums: variants
237    pub variants: Option<Vec<EnumVariantInfo>>,
238    /// All trait implementations
239    pub trait_impls: Vec<String>,
240    /// Inherent methods
241    pub inherent_methods: Vec<MethodSummary>,
242    /// Layout information (if available)
243    pub layout: Option<LayoutInfo>,
244    /// Original source code (if available)
245    pub source: Option<String>,
246    pub span: Option<SpanInfo>,
247}
248
249/// The kind of a type.
250#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
251#[serde(rename_all = "snake_case")]
252pub enum TypeKind {
253    Struct,
254    Enum,
255    Union,
256    Trait,
257    TypeAlias,
258    Primitive,
259    Tuple,
260    Array,
261    Slice,
262    Reference,
263    Pointer,
264    Function,
265    Closure,
266    Opaque,
267}
268
269/// A generic parameter (lifetime, type, or const).
270#[derive(Debug, Clone, Serialize, Deserialize)]
271pub struct GenericParam {
272    pub name: String,
273    pub kind: GenericParamKind,
274    /// Bounds on this parameter
275    pub bounds: Vec<String>,
276    /// Default value (if any)
277    pub default: Option<String>,
278}
279
280#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
281#[serde(rename_all = "snake_case")]
282pub enum GenericParamKind {
283    Lifetime,
284    Type,
285    Const { ty: String },
286}
287
288// ============================================================================
289// Field Information
290// ============================================================================
291
292/// Information about a struct field.
293#[derive(Debug, Clone, Serialize, Deserialize)]
294pub struct FieldInfo {
295    /// Field name (None for tuple struct fields)
296    pub name: Option<String>,
297    /// Field index
298    pub index: usize,
299    /// Type as a string
300    pub ty: String,
301    /// Resolved/canonical type
302    pub resolved_ty: Option<String>,
303    /// Visibility of the field
304    pub visibility: Visibility,
305    /// Doc comments
306    pub docs: Option<String>,
307    /// Attributes
308    pub attributes: Vec<String>,
309    /// Offset in bytes (if layout is known)
310    pub offset: Option<usize>,
311    /// Size in bytes (if layout is known)
312    pub size: Option<usize>,
313    pub span: Option<SpanInfo>,
314}
315
316/// Information about an enum variant.
317#[derive(Debug, Clone, Serialize, Deserialize)]
318pub struct EnumVariantInfo {
319    pub name: String,
320    pub index: usize,
321    /// Fields of this variant
322    pub fields: Vec<FieldInfo>,
323    /// Discriminant value (if specified)
324    pub discriminant: Option<String>,
325    /// Doc comments
326    pub docs: Option<String>,
327    /// Attributes
328    pub attributes: Vec<String>,
329    pub span: Option<SpanInfo>,
330}
331
332// ============================================================================
333// Layout Information
334// ============================================================================
335
336/// Memory layout information for a type.
337#[derive(Debug, Clone, Serialize, Deserialize)]
338pub struct LayoutInfo {
339    /// Size in bytes
340    pub size: usize,
341    /// Alignment in bytes
342    pub align: usize,
343    /// Field offsets (for structs)
344    pub field_offsets: Option<Vec<FieldLayoutInfo>>,
345    /// Variant layouts (for enums)
346    pub variants: Option<Vec<VariantLayoutInfo>>,
347    /// Whether this type is sized
348    pub is_sized: bool,
349    /// Whether this type is Copy
350    pub is_copy: bool,
351    /// Whether this type is Send
352    pub is_send: bool,
353    /// Whether this type is Sync
354    pub is_sync: bool,
355}
356
357#[derive(Debug, Clone, Serialize, Deserialize)]
358pub struct FieldLayoutInfo {
359    pub name: Option<String>,
360    pub index: usize,
361    pub offset: usize,
362    pub size: usize,
363}
364
365#[derive(Debug, Clone, Serialize, Deserialize)]
366pub struct VariantLayoutInfo {
367    pub name: String,
368    pub discriminant: Option<i128>,
369    pub fields: Vec<FieldLayoutInfo>,
370}
371
372// ============================================================================
373// Impl Information
374// ============================================================================
375
376/// Detailed information about a trait implementation.
377#[derive(Debug, Clone, Serialize, Deserialize)]
378pub struct TraitImplDetails {
379    /// The implementing type
380    pub self_ty: String,
381    /// The trait being implemented
382    pub trait_path: String,
383    /// Generic parameters on the impl
384    pub generics: Vec<GenericParam>,
385    /// Where clause
386    pub where_clause: Option<String>,
387    /// Whether this is a negative impl (!Trait)
388    pub is_negative: bool,
389    /// Whether this is an unsafe impl
390    pub is_unsafe: bool,
391    /// Methods in this impl
392    pub methods: Vec<MethodDetails>,
393    /// Associated types
394    pub assoc_types: Vec<AssocTypeInfo>,
395    /// Associated constants
396    pub assoc_consts: Vec<AssocConstInfo>,
397    /// The full source code of the impl block
398    pub source: Option<String>,
399    pub span: Option<SpanInfo>,
400}
401
402/// Detailed information about an inherent impl block.
403#[derive(Debug, Clone, Serialize, Deserialize)]
404pub struct InherentImplDetails {
405    /// The type this impl is for
406    pub self_ty: String,
407    /// Generic parameters
408    pub generics: Vec<GenericParam>,
409    /// Where clause
410    pub where_clause: Option<String>,
411    /// Whether this is an unsafe impl
412    pub is_unsafe: bool,
413    /// Methods in this impl
414    pub methods: Vec<MethodDetails>,
415    /// Associated constants
416    pub assoc_consts: Vec<AssocConstInfo>,
417    /// Associated types
418    pub assoc_types: Vec<AssocTypeInfo>,
419    /// The full source code
420    pub source: Option<String>,
421    pub span: Option<SpanInfo>,
422}
423
424/// Summary of a method (for listings).
425#[derive(Debug, Clone, Serialize, Deserialize)]
426pub struct MethodSummary {
427    pub name: String,
428    pub path: String,
429    pub signature: String,
430    pub is_unsafe: bool,
431    pub is_const: bool,
432    pub is_async: bool,
433}
434
435/// Detailed information about a method.
436#[derive(Debug, Clone, Serialize, Deserialize)]
437pub struct MethodDetails {
438    pub name: String,
439    pub path: String,
440    /// Full signature as a string
441    pub signature: String,
442    /// Parsed signature components
443    pub parsed_signature: FunctionSignature,
444    /// Whether this has a default implementation
445    pub has_body: bool,
446    /// Method body source code (if available)
447    pub body_source: Option<String>,
448    /// Body as tokens (simplified AST)
449    pub body_tokens: Option<Vec<Token>>,
450    /// Whether this is unsafe
451    pub is_unsafe: bool,
452    /// Whether this is const
453    pub is_const: bool,
454    /// Whether this is async
455    pub is_async: bool,
456    /// Doc comments
457    pub docs: Option<String>,
458    /// Attributes
459    pub attributes: Vec<String>,
460    pub span: Option<SpanInfo>,
461}
462
463/// Parsed function signature.
464#[derive(Debug, Clone, Serialize, Deserialize)]
465pub struct FunctionSignature {
466    /// Receiver (self, &self, &mut self, etc.)
467    pub receiver: Option<ReceiverInfo>,
468    /// Parameters (excluding self)
469    pub params: Vec<ParamInfo>,
470    /// Return type
471    pub return_ty: Option<String>,
472    /// Generic parameters
473    pub generics: Vec<GenericParam>,
474    /// Where clause
475    pub where_clause: Option<String>,
476}
477
478#[derive(Debug, Clone, Serialize, Deserialize)]
479pub struct ReceiverInfo {
480    /// "self", "&self", "&mut self", "self: Pin<&mut Self>", etc.
481    pub kind: String,
482    /// Whether it's mutable
483    pub is_mut: bool,
484    /// Whether it's a reference
485    pub is_ref: bool,
486    /// Lifetime (if reference)
487    pub lifetime: Option<String>,
488}
489
490#[derive(Debug, Clone, Serialize, Deserialize)]
491pub struct ParamInfo {
492    pub name: String,
493    pub ty: String,
494    pub is_mut: bool,
495}
496
497/// Associated type information.
498#[derive(Debug, Clone, Serialize, Deserialize)]
499pub struct AssocTypeInfo {
500    pub name: String,
501    /// The concrete type (in an impl)
502    pub ty: Option<String>,
503    /// Bounds (in a trait definition)
504    pub bounds: Vec<String>,
505    /// Default type (in a trait definition)
506    pub default: Option<String>,
507    pub docs: Option<String>,
508    pub span: Option<SpanInfo>,
509}
510
511/// Associated constant information.
512#[derive(Debug, Clone, Serialize, Deserialize)]
513pub struct AssocConstInfo {
514    pub name: String,
515    pub ty: String,
516    /// The value (if specified)
517    pub value: Option<String>,
518    pub docs: Option<String>,
519    pub span: Option<SpanInfo>,
520}
521
522// ============================================================================
523// Trait Information
524// ============================================================================
525
526/// Summary information about a trait.
527#[derive(Debug, Clone, Serialize, Deserialize)]
528pub struct TraitInfo {
529    pub name: String,
530    pub path: String,
531    pub generics: Vec<GenericParam>,
532    /// Number of required methods
533    pub required_methods: usize,
534    /// Number of provided methods
535    pub provided_methods: usize,
536    /// Supertraits
537    pub supertraits: Vec<String>,
538}
539
540/// Detailed information about a trait.
541#[derive(Debug, Clone, Serialize, Deserialize)]
542pub struct TraitDetails {
543    pub name: String,
544    pub path: String,
545    pub visibility: Visibility,
546    pub generics: Vec<GenericParam>,
547    pub where_clause: Option<String>,
548    /// Is this an auto trait?
549    pub is_auto: bool,
550    /// Is this an unsafe trait?
551    pub is_unsafe: bool,
552    /// Supertraits
553    pub supertraits: Vec<String>,
554    /// Methods defined in this trait
555    pub methods: Vec<TraitMethodInfo>,
556    /// Associated types
557    pub assoc_types: Vec<AssocTypeInfo>,
558    /// Associated constants
559    pub assoc_consts: Vec<AssocConstInfo>,
560    /// Doc comments
561    pub docs: Option<String>,
562    /// Attributes
563    pub attributes: Vec<String>,
564    /// Full source code
565    pub source: Option<String>,
566    /// Types that implement this trait (in the current crate)
567    pub implementors: Vec<String>,
568    pub span: Option<SpanInfo>,
569}
570
571/// Information about a trait method.
572#[derive(Debug, Clone, Serialize, Deserialize)]
573pub struct TraitMethodInfo {
574    pub name: String,
575    pub signature: String,
576    pub parsed_signature: FunctionSignature,
577    /// Does this method have a default implementation?
578    pub has_default: bool,
579    /// Default implementation source
580    pub default_body: Option<String>,
581    pub is_unsafe: bool,
582    pub docs: Option<String>,
583    pub attributes: Vec<String>,
584    pub span: Option<SpanInfo>,
585}
586
587// ============================================================================
588// Token/AST Information
589// ============================================================================
590
591/// Simplified token representation for method bodies.
592#[derive(Debug, Clone, Serialize, Deserialize)]
593#[serde(tag = "token_type", rename_all = "snake_case")]
594pub enum Token {
595    /// An identifier
596    Ident { name: String },
597    /// A literal value
598    Literal { kind: LiteralKind, value: String },
599    /// A punctuation symbol
600    Punct { ch: char },
601    /// A keyword
602    Keyword { name: String },
603    /// A group (delimited tokens)
604    Group {
605        delimiter: Delimiter,
606        tokens: Vec<Token>,
607    },
608    /// A path (e.g., std::collections::HashMap)
609    Path { segments: Vec<String> },
610    /// A method call
611    MethodCall {
612        receiver: Box<Token>,
613        method: String,
614        args: Vec<Token>,
615    },
616    /// A function call
617    FnCall { path: Vec<String>, args: Vec<Token> },
618    /// A field access
619    FieldAccess { base: Box<Token>, field: String },
620    /// A binary operation
621    BinOp {
622        lhs: Box<Token>,
623        op: String,
624        rhs: Box<Token>,
625    },
626    /// A unary operation
627    UnaryOp { op: String, expr: Box<Token> },
628    /// An if expression
629    If {
630        cond: Box<Token>,
631        then_branch: Vec<Token>,
632        else_branch: Option<Vec<Token>>,
633    },
634    /// A match expression
635    Match {
636        expr: Box<Token>,
637        arms: Vec<MatchArm>,
638    },
639    /// A let binding
640    Let {
641        pattern: String,
642        ty: Option<String>,
643        init: Option<Box<Token>>,
644    },
645    /// A return statement
646    Return { expr: Option<Box<Token>> },
647    /// A block
648    Block { stmts: Vec<Token> },
649    /// A closure
650    Closure {
651        params: Vec<String>,
652        body: Box<Token>,
653    },
654    /// Raw source when we can't parse further
655    Raw { source: String },
656}
657
658#[derive(Debug, Clone, Serialize, Deserialize)]
659pub struct MatchArm {
660    pub pattern: String,
661    pub guard: Option<String>,
662    pub body: Vec<Token>,
663}
664
665#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
666#[serde(rename_all = "snake_case")]
667pub enum LiteralKind {
668    String,
669    ByteString,
670    Char,
671    Byte,
672    Int,
673    Float,
674    Bool,
675}
676
677#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
678#[serde(rename_all = "snake_case")]
679pub enum Delimiter {
680    Paren,
681    Bracket,
682    Brace,
683    None,
684}
685
686// ============================================================================
687// Cached/Extracted Type Information
688// ============================================================================
689
690/// Complete extracted type information for a crate.
691/// This is what the daemon caches after compilation.
692#[derive(Debug, Clone, Default, Serialize, Deserialize)]
693pub struct CrateTypeInfo {
694    /// Name of the crate
695    pub crate_name: String,
696    /// Crate version (if known)
697    pub crate_version: Option<String>,
698
699    /// All items in the crate
700    pub items: Vec<ItemInfo>,
701
702    /// Detailed type information (structs, enums, unions)
703    pub types: HashMap<String, TypeDetails>,
704
705    /// All trait definitions
706    pub traits: HashMap<String, TraitDetails>,
707
708    /// Trait implementations (keyed by implementing type)
709    pub trait_impls: HashMap<String, Vec<TraitImplDetails>>,
710
711    /// Inherent impls (keyed by type)
712    pub inherent_impls: HashMap<String, Vec<InherentImplDetails>>,
713
714    /// Type aliases (path -> resolved type)
715    pub type_aliases: HashMap<String, TypeAliasInfo>,
716
717    /// Layout information (keyed by type path)
718    pub layouts: HashMap<String, LayoutInfo>,
719
720    /// Module tree for path matching
721    pub modules: HashMap<String, ModuleInfo>,
722}
723
724/// Information about a type alias.
725#[derive(Debug, Clone, Serialize, Deserialize)]
726pub struct TypeAliasInfo {
727    pub name: String,
728    pub path: String,
729    pub generics: Vec<GenericParam>,
730    /// The aliased type
731    pub ty: String,
732    /// Fully resolved type (following all aliases)
733    pub resolved_ty: String,
734    pub visibility: Visibility,
735    pub docs: Option<String>,
736    pub span: Option<SpanInfo>,
737}
738
739/// Information about a module.
740#[derive(Debug, Clone, Serialize, Deserialize)]
741pub struct ModuleInfo {
742    pub name: String,
743    pub path: String,
744    pub visibility: Visibility,
745    /// Child items (names only)
746    pub items: Vec<String>,
747    /// Re-exports
748    pub reexports: Vec<ReexportInfo>,
749}
750
751#[derive(Debug, Clone, Serialize, Deserialize)]
752pub struct ReexportInfo {
753    /// The name as exported
754    pub name: String,
755    /// The original path
756    pub original_path: String,
757    pub visibility: Visibility,
758}
759
760// ============================================================================
761// Utility Functions
762// ============================================================================
763
764/// Default socket path for the Bronzite daemon.
765pub fn default_socket_path() -> std::path::PathBuf {
766    std::env::temp_dir().join("bronzite.sock")
767}
768
769/// Socket path for a specific crate/workspace.
770pub fn socket_path_for_workspace(workspace_root: &std::path::Path) -> std::path::PathBuf {
771    use std::collections::hash_map::DefaultHasher;
772    use std::hash::{Hash, Hasher};
773
774    let mut hasher = DefaultHasher::new();
775    workspace_root.hash(&mut hasher);
776    let hash = hasher.finish();
777
778    std::env::temp_dir().join(format!("bronzite-{:x}.sock", hash))
779}
780
781// ============================================================================
782// Pattern Matching for FindTypes
783// ============================================================================
784
785/// Check if a path matches a pattern.
786/// Supports:
787/// - Exact match: "foo::Bar"
788/// - Glob suffix: "foo::*"
789/// - Recursive glob: "foo::**"
790/// - Wildcards: "foo::Bar*"
791pub fn path_matches_pattern(path: &str, pattern: &str) -> bool {
792    let pattern = pattern.trim();
793    let path = path.trim();
794
795    // Recursive glob: foo::** matches foo::bar::baz
796    if pattern.ends_with("::**") {
797        let prefix = &pattern[..pattern.len() - 4];
798        return path == prefix || path.starts_with(&format!("{}::", prefix));
799    }
800
801    // Single level glob: foo::* matches foo::bar but not foo::bar::baz
802    if pattern.ends_with("::*") {
803        let prefix = &pattern[..pattern.len() - 3];
804        if !path.starts_with(&format!("{}::", prefix)) {
805            return false;
806        }
807        let suffix = &path[prefix.len() + 2..];
808        return !suffix.contains("::");
809    }
810
811    // Wildcard in name: foo::Bar* matches foo::BarBaz
812    if pattern.contains('*') {
813        let parts: Vec<&str> = pattern.split('*').collect();
814        if parts.len() != 2 {
815            return false; // Only support single wildcard for now
816        }
817        return path.starts_with(parts[0]) && path.ends_with(parts[1]);
818    }
819
820    // Exact match
821    path == pattern
822}
823
824#[cfg(test)]
825mod tests {
826    use super::*;
827
828    #[test]
829    fn test_path_matching() {
830        // Exact match
831        assert!(path_matches_pattern("foo::Bar", "foo::Bar"));
832        assert!(!path_matches_pattern("foo::Baz", "foo::Bar"));
833
834        // Single level glob
835        assert!(path_matches_pattern("foo::Bar", "foo::*"));
836        assert!(path_matches_pattern("foo::Baz", "foo::*"));
837        assert!(!path_matches_pattern("foo::bar::Baz", "foo::*"));
838
839        // Recursive glob
840        assert!(path_matches_pattern("foo::Bar", "foo::**"));
841        assert!(path_matches_pattern("foo::bar::Baz", "foo::**"));
842        assert!(path_matches_pattern("foo::bar::baz::Qux", "foo::**"));
843        assert!(!path_matches_pattern("bar::Baz", "foo::**"));
844
845        // Wildcard
846        assert!(path_matches_pattern("foo::BarBaz", "foo::Bar*"));
847        assert!(path_matches_pattern("foo::Bar", "foo::Bar*"));
848        assert!(!path_matches_pattern("foo::Baz", "foo::Bar*"));
849    }
850
851    #[test]
852    fn test_query_serialization() {
853        let query = Query::CheckImpl {
854            type_path: "Foo".to_string(),
855            trait_path: "MyTrait".to_string(),
856        };
857        let json = serde_json::to_string(&query).unwrap();
858        let parsed: Query = serde_json::from_str(&json).unwrap();
859
860        match parsed {
861            Query::CheckImpl {
862                type_path,
863                trait_path,
864            } => {
865                assert_eq!(type_path, "Foo");
866                assert_eq!(trait_path, "MyTrait");
867            }
868            _ => panic!("Wrong query type"),
869        }
870    }
871
872    #[test]
873    fn test_response_serialization() {
874        let response = Response {
875            id: 42,
876            result: QueryResult::Success {
877                data: QueryData::ImplCheck {
878                    implements: true,
879                    impl_info: None,
880                },
881            },
882        };
883        let json = serde_json::to_string(&response).unwrap();
884        let parsed: Response = serde_json::from_str(&json).unwrap();
885
886        assert_eq!(parsed.id, 42);
887    }
888}