bronzite_client/reflection.rs
1//! High-level reflection API for Bronzite.
2//!
3//! This module provides an ergonomic, type-safe API for compile-time reflection.
4//! Types hold references to the client and can navigate relationships fluently.
5//!
6//! # Example
7//!
8//! ```ignore
9//! use bronzite_client::Crate;
10//!
11//! let krate = Crate::reflect("my_crate")?;
12//!
13//! // Query items with patterns
14//! let items = krate.items("bevy::prelude::*")?;
15//!
16//! // Get a specific struct and explore it
17//! let user = krate.get_struct("User")?;
18//! for field in user.fields()? {
19//! println!("{}: {} (size: {})",
20//! field.name,
21//! field.ty,
22//! field.size.unwrap_or(0)
23//! );
24//! }
25//!
26//! // Check trait implementations
27//! if user.implements("Debug")? {
28//! println!("User implements Debug");
29//! }
30//! ```
31
32use crate::{BronziteClient, Error, Result};
33use bronzite_types::{
34 AssocConstInfo, AssocTypeInfo, FieldInfo as RawFieldInfo, FunctionSignature, GenericParam,
35 LayoutInfo, MethodDetails as RawMethodDetails, TraitDetails as RawTraitDetails,
36 TraitImplDetails as RawTraitImpl, TypeDetails, TypeSummary, Visibility,
37};
38use std::sync::Arc;
39
40// ============================================================================
41// Core Reflection Entry Point
42// ============================================================================
43
44/// A reflected crate - the main entry point for type reflection.
45pub struct Crate {
46 name: String,
47 client: Arc<BronziteClient>,
48}
49
50impl Crate {
51 /// Reflect on a crate by name.
52 ///
53 /// This will connect to the daemon (starting it if needed) and return
54 /// a handle for querying types in the specified crate.
55 pub fn reflect(crate_name: impl Into<String>) -> Result<Self> {
56 crate::ensure_daemon_running(None)?;
57 let client = crate::connect()?;
58 Ok(Self {
59 name: crate_name.into(),
60 client: Arc::new(client),
61 })
62 }
63
64 /// Get the crate name.
65 pub fn name(&self) -> &str {
66 &self.name
67 }
68
69 /// Get all items matching a pattern.
70 ///
71 /// Supports:
72 /// - Exact: `"foo::Bar"`
73 /// - Wildcard: `"foo::Bar*"`
74 /// - Single-level glob: `"foo::*"` (matches `foo::Bar` but not `foo::bar::Baz`)
75 /// - Recursive glob: `"foo::**"` (matches all descendants)
76 pub fn items(&self, pattern: &str) -> Result<Vec<Item>> {
77 let types = self.client_mut()?.find_types(&self.name, pattern)?;
78
79 types
80 .into_iter()
81 .map(|summary| Item::from_summary(summary, &self.name, Arc::clone(&self.client)))
82 .collect()
83 }
84
85 /// Get all structs matching a pattern.
86 pub fn structs(&self, pattern: &str) -> Result<Vec<StructDef>> {
87 let items = self.items(pattern)?;
88 Ok(items
89 .into_iter()
90 .filter_map(|item| match item {
91 Item::Struct(s) => Some(s),
92 _ => None,
93 })
94 .collect())
95 }
96
97 /// Get all enums matching a pattern.
98 pub fn enums(&self, pattern: &str) -> Result<Vec<EnumDef>> {
99 let items = self.items(pattern)?;
100 Ok(items
101 .into_iter()
102 .filter_map(|item| match item {
103 Item::Enum(e) => Some(e),
104 _ => None,
105 })
106 .collect())
107 }
108
109 /// Get all traits matching a pattern.
110 pub fn traits(&self, pattern: &str) -> Result<Vec<TraitDef>> {
111 let all_traits = self.client_mut()?.get_traits(&self.name)?;
112
113 let matching: Vec<_> = all_traits
114 .into_iter()
115 .filter(|t| bronzite_types::path_matches_pattern(&t.path, pattern))
116 .collect();
117
118 matching
119 .into_iter()
120 .map(|info| TraitDef::from_info(info, &self.name, Arc::clone(&self.client)))
121 .collect()
122 }
123
124 /// Get a specific struct by path.
125 pub fn get_struct(&self, path: &str) -> Result<StructDef> {
126 let details = self.client_mut()?.get_type(&self.name, path)?;
127 StructDef::from_details(details, &self.name, Arc::clone(&self.client))
128 }
129
130 /// Get a specific enum by path.
131 pub fn get_enum(&self, path: &str) -> Result<EnumDef> {
132 let details = self.client_mut()?.get_type(&self.name, path)?;
133 EnumDef::from_details(details, &self.name, Arc::clone(&self.client))
134 }
135
136 /// Get a specific trait by path.
137 pub fn get_trait(&self, path: &str) -> Result<TraitDef> {
138 let details = self.client_mut()?.get_trait(&self.name, path)?;
139 TraitDef::from_trait_details(details, &self.name, Arc::clone(&self.client))
140 }
141
142 /// Get a specific type alias by path.
143 pub fn get_type_alias(&self, path: &str) -> Result<TypeAliasDef> {
144 let (original, resolved, chain) = self.client_mut()?.resolve_alias(&self.name, path)?;
145 Ok(TypeAliasDef {
146 path: original,
147 resolved_path: resolved,
148 resolution_chain: chain,
149 crate_name: self.name.clone(),
150 client: Arc::clone(&self.client),
151 })
152 }
153
154 /// Helper to get mutable client access (Arc doesn't need Mutex for single-threaded use).
155 fn client_mut(&self) -> Result<&mut BronziteClient> {
156 // SAFETY: This is safe in proc-macro context where we're single-threaded.
157 // Arc is used for cheap cloning, not thread-safety here.
158 unsafe {
159 let ptr = Arc::as_ptr(&self.client) as *mut BronziteClient;
160 Ok(&mut *ptr)
161 }
162 }
163}
164
165// ============================================================================
166// Item Enum - Unified Type Representation
167// ============================================================================
168
169/// A unified representation of any Rust item (struct, enum, trait, etc).
170///
171/// This enum provides a type-safe way to work with different kinds of items
172/// discovered through pattern matching or queries. Each variant contains
173/// a specific type definition with navigation methods.
174///
175/// # Example
176///
177/// ```ignore
178/// use bronzite_client::{Crate, Item};
179///
180/// let krate = Crate::reflect("my_crate")?;
181/// for item in krate.items("*")? {
182/// match item {
183/// Item::Struct(s) => println!("Struct: {}", s.name),
184/// Item::Enum(e) => println!("Enum: {}", e.name),
185/// Item::Trait(t) => println!("Trait: {}", t.name),
186/// Item::TypeAlias(a) => println!("Alias: {}", a.path),
187/// Item::Union(u) => println!("Union: {}", u.name),
188/// }
189/// }
190/// ```
191#[derive(Debug, Clone)]
192pub enum Item {
193 /// A struct definition
194 Struct(StructDef),
195 /// An enum definition
196 Enum(EnumDef),
197 /// A trait definition
198 Trait(TraitDef),
199 /// A type alias
200 TypeAlias(TypeAliasDef),
201 /// A union definition
202 Union(UnionDef),
203}
204
205impl Item {
206 /// Get the name of this item.
207 pub fn name(&self) -> &str {
208 match self {
209 Item::Struct(s) => &s.name,
210 Item::Enum(e) => &e.name,
211 Item::Trait(t) => &t.name,
212 Item::TypeAlias(a) => &a.path,
213 Item::Union(u) => &u.name,
214 }
215 }
216
217 /// Get the full path of this item.
218 pub fn path(&self) -> &str {
219 match self {
220 Item::Struct(s) => &s.path,
221 Item::Enum(e) => &e.path,
222 Item::Trait(t) => &t.path,
223 Item::TypeAlias(a) => &a.path,
224 Item::Union(u) => &u.path,
225 }
226 }
227
228 fn from_summary(
229 summary: TypeSummary,
230 crate_name: &str,
231 client: Arc<BronziteClient>,
232 ) -> Result<Self> {
233 match summary.kind {
234 bronzite_types::TypeKind::Struct => Ok(Item::Struct(StructDef {
235 name: summary.name,
236 path: summary.path,
237 generics: summary.generics,
238 crate_name: crate_name.to_string(),
239 client,
240 cached_details: None,
241 })),
242 bronzite_types::TypeKind::Enum => Ok(Item::Enum(EnumDef {
243 name: summary.name,
244 path: summary.path,
245 generics: summary.generics,
246 crate_name: crate_name.to_string(),
247 client,
248 cached_details: None,
249 })),
250 bronzite_types::TypeKind::Union => Ok(Item::Union(UnionDef {
251 name: summary.name,
252 path: summary.path,
253 generics: summary.generics,
254 crate_name: crate_name.to_string(),
255 client,
256 })),
257 bronzite_types::TypeKind::Trait => {
258 // For traits, we need to fetch full details
259 let client_mut = unsafe {
260 let ptr = Arc::as_ptr(&client) as *mut BronziteClient;
261 &mut *ptr
262 };
263 let details = client_mut.get_trait(crate_name, &summary.path)?;
264 Ok(Item::Trait(TraitDef::from_trait_details(
265 details, crate_name, client,
266 )?))
267 }
268 _ => Err(Error::UnexpectedResponse),
269 }
270 }
271}
272
273// ============================================================================
274// Struct Definition
275// ============================================================================
276
277/// A reflected struct definition with navigation methods.
278///
279/// Provides access to struct metadata and navigation to related types like
280/// fields, trait implementations, and methods.
281///
282/// # Example
283///
284/// ```ignore
285/// use bronzite_client::Crate;
286///
287/// let krate = Crate::reflect("my_crate")?;
288/// let user = krate.get_struct("User")?;
289///
290/// // Get fields
291/// for field in user.fields()? {
292/// println!("Field: {} of type {}",
293/// field.name.unwrap_or_default(),
294/// field.ty
295/// );
296/// }
297///
298/// // Check trait implementation
299/// if user.implements("Debug")? {
300/// println!("User implements Debug");
301/// }
302///
303/// // Get methods
304/// for method in user.methods()? {
305/// println!("Method: {}", method.name);
306/// }
307/// ```
308#[derive(Debug, Clone)]
309pub struct StructDef {
310 /// The struct's name (without path)
311 pub name: String,
312 /// The struct's full path
313 pub path: String,
314 /// Generic parameters
315 pub generics: Vec<GenericParam>,
316 crate_name: String,
317 client: Arc<BronziteClient>,
318 cached_details: Option<Box<TypeDetails>>,
319}
320
321impl StructDef {
322 fn from_details(
323 details: TypeDetails,
324 crate_name: &str,
325 client: Arc<BronziteClient>,
326 ) -> Result<Self> {
327 Ok(Self {
328 name: details.name.clone(),
329 path: details.path.clone(),
330 generics: details.generics.clone(),
331 crate_name: crate_name.to_string(),
332 client,
333 cached_details: Some(Box::new(details)),
334 })
335 }
336
337 /// Get all fields of this struct.
338 ///
339 /// Returns a vector of [`Field`] objects, each representing a field in the struct.
340 /// Fields include metadata like name, type, visibility, size, and offset.
341 ///
342 /// # Example
343 ///
344 /// ```ignore
345 /// let user = krate.get_struct("User")?;
346 /// for field in user.fields()? {
347 /// println!("Field: {} of type {}",
348 /// field.name.as_deref().unwrap_or("<unnamed>"),
349 /// field.ty
350 /// );
351 /// if let Some(size) = field.size {
352 /// println!(" Size: {} bytes", size);
353 /// }
354 /// }
355 /// ```
356 pub fn fields(&self) -> Result<Vec<Field>> {
357 let fields = self
358 .client_mut()?
359 .get_fields(&self.crate_name, &self.path)?;
360 Ok(fields
361 .into_iter()
362 .map(|f| Field::from_raw(f, &self.crate_name, Arc::clone(&self.client)))
363 .collect())
364 }
365
366 /// Get all trait implementations for this struct.
367 ///
368 /// Returns a vector of [`TraitImpl`] objects containing information about each
369 /// trait implementation, including methods, associated types, and source code.
370 ///
371 /// # Example
372 ///
373 /// ```ignore
374 /// let user = krate.get_struct("User")?;
375 /// for impl_block in user.trait_impls()? {
376 /// println!("Implements: {}", impl_block.trait_path);
377 /// for method in impl_block.methods() {
378 /// println!(" - {}", method.name);
379 /// }
380 /// }
381 /// ```
382 pub fn trait_impls(&self) -> Result<Vec<TraitImpl>> {
383 let impls = self
384 .client_mut()?
385 .get_trait_impls(&self.crate_name, &self.path)?;
386 Ok(impls
387 .into_iter()
388 .map(|i| TraitImpl::from_raw(i, &self.crate_name, Arc::clone(&self.client)))
389 .collect())
390 }
391
392 /// Check if this struct implements a specific trait.
393 ///
394 /// This is a convenient way to test for trait implementation without
395 /// fetching all trait impls.
396 ///
397 /// # Arguments
398 ///
399 /// * `trait_path` - The trait path to check (e.g., "Debug", "std::fmt::Display")
400 ///
401 /// # Example
402 ///
403 /// ```ignore
404 /// let user = krate.get_struct("User")?;
405 /// if user.implements("Debug")? {
406 /// println!("User can be debug-printed");
407 /// }
408 /// if user.implements("std::clone::Clone")? {
409 /// println!("User can be cloned");
410 /// }
411 /// ```
412 pub fn implements(&self, trait_path: &str) -> Result<bool> {
413 let (implements, _) =
414 self.client_mut()?
415 .check_impl(&self.crate_name, &self.path, trait_path)?;
416 Ok(implements)
417 }
418
419 /// Get inherent methods (from `impl StructName { ... }` blocks).
420 ///
421 /// Returns methods defined in inherent impl blocks, not trait implementations.
422 /// Each [`Method`] includes the signature, body source, and navigation to
423 /// parameter/return types.
424 ///
425 /// # Example
426 ///
427 /// ```ignore
428 /// let user = krate.get_struct("User")?;
429 /// for method in user.methods()? {
430 /// println!("Method: {}", method.signature);
431 /// if let Some(body) = &method.body_source {
432 /// println!(" Implementation: {}", body);
433 /// }
434 /// if let Some(ret_type) = method.return_type_def()? {
435 /// println!(" Returns: {}", ret_type.name());
436 /// }
437 /// }
438 /// ```
439 pub fn methods(&self) -> Result<Vec<Method>> {
440 let impls = self
441 .client_mut()?
442 .get_inherent_impls(&self.crate_name, &self.path)?;
443 Ok(impls
444 .into_iter()
445 .flat_map(|impl_block| {
446 impl_block
447 .methods
448 .into_iter()
449 .map(|m| Method::from_raw(m, &self.crate_name, Arc::clone(&self.client)))
450 })
451 .collect())
452 }
453
454 /// Get memory layout information for this struct.
455 ///
456 /// Returns [`LayoutInfo`] containing size, alignment, field offsets,
457 /// and auto-trait implementations (Send, Sync, Copy).
458 ///
459 /// # Example
460 ///
461 /// ```ignore
462 /// let user = krate.get_struct("User")?;
463 /// let layout = user.layout()?;
464 /// println!("Size: {} bytes", layout.size);
465 /// println!("Alignment: {} bytes", layout.align);
466 /// println!("Is Copy: {}", layout.is_copy);
467 /// ```
468 pub fn layout(&self) -> Result<LayoutInfo> {
469 self.client_mut()?.get_layout(&self.crate_name, &self.path)
470 }
471
472 /// Get the source code of this struct definition.
473 pub fn source(&self) -> Option<&str> {
474 self.details().and_then(|d| d.source.as_deref())
475 }
476
477 /// Get detailed type information.
478 pub fn details(&self) -> Option<&TypeDetails> {
479 self.cached_details.as_deref()
480 }
481
482 /// Get visibility of this struct.
483 pub fn visibility(&self) -> Option<&Visibility> {
484 self.details().map(|d| &d.visibility)
485 }
486
487 /// Get doc comments.
488 pub fn docs(&self) -> Option<&str> {
489 self.details().and_then(|d| d.docs.as_deref())
490 }
491
492 fn client_mut(&self) -> Result<&mut BronziteClient> {
493 unsafe {
494 let ptr = Arc::as_ptr(&self.client) as *mut BronziteClient;
495 Ok(&mut *ptr)
496 }
497 }
498}
499
500// ============================================================================
501// Enum Definition
502// ============================================================================
503
504/// A reflected enum definition.
505#[derive(Debug, Clone)]
506pub struct EnumDef {
507 pub name: String,
508 pub path: String,
509 pub generics: Vec<GenericParam>,
510 crate_name: String,
511 client: Arc<BronziteClient>,
512 cached_details: Option<Box<TypeDetails>>,
513}
514
515impl EnumDef {
516 fn from_details(
517 details: TypeDetails,
518 crate_name: &str,
519 client: Arc<BronziteClient>,
520 ) -> Result<Self> {
521 Ok(Self {
522 name: details.name.clone(),
523 path: details.path.clone(),
524 generics: details.generics.clone(),
525 crate_name: crate_name.to_string(),
526 client,
527 cached_details: Some(Box::new(details)),
528 })
529 }
530
531 /// Get the enum's variants.
532 pub fn variants(&self) -> Option<&[bronzite_types::EnumVariantInfo]> {
533 self.details().and_then(|d| d.variants.as_deref())
534 }
535
536 /// Get trait implementations for this enum.
537 pub fn trait_impls(&self) -> Result<Vec<TraitImpl>> {
538 let impls = self
539 .client_mut()?
540 .get_trait_impls(&self.crate_name, &self.path)?;
541 Ok(impls
542 .into_iter()
543 .map(|i| TraitImpl::from_raw(i, &self.crate_name, Arc::clone(&self.client)))
544 .collect())
545 }
546
547 /// Check if this enum implements a specific trait.
548 pub fn implements(&self, trait_path: &str) -> Result<bool> {
549 let (implements, _) =
550 self.client_mut()?
551 .check_impl(&self.crate_name, &self.path, trait_path)?;
552 Ok(implements)
553 }
554
555 /// Get inherent methods.
556 pub fn methods(&self) -> Result<Vec<Method>> {
557 let impls = self
558 .client_mut()?
559 .get_inherent_impls(&self.crate_name, &self.path)?;
560 Ok(impls
561 .into_iter()
562 .flat_map(|impl_block| {
563 impl_block
564 .methods
565 .into_iter()
566 .map(|m| Method::from_raw(m, &self.crate_name, Arc::clone(&self.client)))
567 })
568 .collect())
569 }
570
571 /// Get the source code of this enum definition.
572 pub fn source(&self) -> Option<&str> {
573 self.details().and_then(|d| d.source.as_deref())
574 }
575
576 pub fn details(&self) -> Option<&TypeDetails> {
577 self.cached_details.as_deref()
578 }
579
580 pub fn visibility(&self) -> Option<&Visibility> {
581 self.details().map(|d| &d.visibility)
582 }
583
584 pub fn docs(&self) -> Option<&str> {
585 self.details().and_then(|d| d.docs.as_deref())
586 }
587
588 fn client_mut(&self) -> Result<&mut BronziteClient> {
589 unsafe {
590 let ptr = Arc::as_ptr(&self.client) as *mut BronziteClient;
591 Ok(&mut *ptr)
592 }
593 }
594}
595
596// ============================================================================
597// Union Definition
598// ============================================================================
599
600/// A reflected union definition.
601#[derive(Debug, Clone)]
602pub struct UnionDef {
603 pub name: String,
604 pub path: String,
605 pub generics: Vec<GenericParam>,
606 crate_name: String,
607 client: Arc<BronziteClient>,
608}
609
610impl UnionDef {
611 /// Get the union's fields.
612 pub fn fields(&self) -> Result<Vec<Field>> {
613 let fields = self
614 .client_mut()?
615 .get_fields(&self.crate_name, &self.path)?;
616 Ok(fields
617 .into_iter()
618 .map(|f| Field::from_raw(f, &self.crate_name, Arc::clone(&self.client)))
619 .collect())
620 }
621
622 fn client_mut(&self) -> Result<&mut BronziteClient> {
623 unsafe {
624 let ptr = Arc::as_ptr(&self.client) as *mut BronziteClient;
625 Ok(&mut *ptr)
626 }
627 }
628}
629
630// ============================================================================
631// Trait Definition
632// ============================================================================
633
634/// A reflected trait definition.
635#[derive(Debug, Clone)]
636pub struct TraitDef {
637 pub name: String,
638 pub path: String,
639 pub generics: Vec<GenericParam>,
640 pub is_auto: bool,
641 pub is_unsafe: bool,
642 pub supertraits: Vec<String>,
643 pub source: Option<String>,
644 pub docs: Option<String>,
645 crate_name: String,
646 client: Arc<BronziteClient>,
647 cached_details: Option<Box<RawTraitDetails>>,
648}
649
650impl TraitDef {
651 fn from_info(
652 info: bronzite_types::TraitInfo,
653 crate_name: &str,
654 client: Arc<BronziteClient>,
655 ) -> Result<Self> {
656 // Fetch full details
657 let client_mut = unsafe {
658 let ptr = Arc::as_ptr(&client) as *mut BronziteClient;
659 &mut *ptr
660 };
661 let details = client_mut.get_trait(crate_name, &info.path)?;
662 Self::from_trait_details(details, crate_name, client)
663 }
664
665 fn from_trait_details(
666 details: RawTraitDetails,
667 crate_name: &str,
668 client: Arc<BronziteClient>,
669 ) -> Result<Self> {
670 Ok(Self {
671 name: details.name.clone(),
672 path: details.path.clone(),
673 generics: details.generics.clone(),
674 is_auto: details.is_auto,
675 is_unsafe: details.is_unsafe,
676 supertraits: details.supertraits.clone(),
677 source: details.source.clone(),
678 docs: details.docs.clone(),
679 crate_name: crate_name.to_string(),
680 client,
681 cached_details: Some(Box::new(details)),
682 })
683 }
684
685 /// Get all methods defined in this trait.
686 pub fn methods(&self) -> Vec<TraitMethod> {
687 self.cached_details
688 .as_ref()
689 .map(|d| {
690 d.methods
691 .iter()
692 .map(|m| TraitMethod {
693 name: m.name.clone(),
694 signature: m.signature.clone(),
695 parsed_signature: m.parsed_signature.clone(),
696 has_default: m.has_default,
697 default_body: m.default_body.clone(),
698 is_unsafe: m.is_unsafe,
699 docs: m.docs.clone(),
700 })
701 .collect()
702 })
703 .unwrap_or_default()
704 }
705
706 /// Get associated types.
707 pub fn associated_types(&self) -> Vec<&AssocTypeInfo> {
708 self.cached_details
709 .as_ref()
710 .map(|d| d.assoc_types.iter().collect())
711 .unwrap_or_default()
712 }
713
714 /// Get associated constants.
715 pub fn associated_consts(&self) -> Vec<&AssocConstInfo> {
716 self.cached_details
717 .as_ref()
718 .map(|d| d.assoc_consts.iter().collect())
719 .unwrap_or_default()
720 }
721
722 /// Get all types that implement this trait.
723 pub fn implementors(&self) -> Result<Vec<Item>> {
724 let types = self
725 .client_mut()?
726 .get_implementors(&self.crate_name, &self.path)?;
727 types
728 .into_iter()
729 .map(|summary| Item::from_summary(summary, &self.crate_name, Arc::clone(&self.client)))
730 .collect()
731 }
732
733 fn client_mut(&self) -> Result<&mut BronziteClient> {
734 unsafe {
735 let ptr = Arc::as_ptr(&self.client) as *mut BronziteClient;
736 Ok(&mut *ptr)
737 }
738 }
739}
740
741/// A method defined in a trait.
742#[derive(Debug, Clone)]
743pub struct TraitMethod {
744 pub name: String,
745 pub signature: String,
746 pub parsed_signature: FunctionSignature,
747 pub has_default: bool,
748 pub default_body: Option<String>,
749 pub is_unsafe: bool,
750 pub docs: Option<String>,
751}
752
753// ============================================================================
754// Type Alias Definition
755// ============================================================================
756
757/// A reflected type alias.
758#[derive(Debug, Clone)]
759pub struct TypeAliasDef {
760 pub path: String,
761 pub resolved_path: String,
762 pub resolution_chain: Vec<String>,
763 crate_name: String,
764 client: Arc<BronziteClient>,
765}
766
767impl TypeAliasDef {
768 /// Resolve this alias to its concrete type.
769 pub fn resolve(&self) -> Result<Item> {
770 // Get the final resolved type
771 let details = self
772 .client_mut()?
773 .get_type(&self.crate_name, &self.resolved_path)?;
774
775 let summary = TypeSummary {
776 name: details.name.clone(),
777 path: details.path.clone(),
778 kind: details.kind.clone(),
779 generics: details.generics.clone(),
780 };
781
782 Item::from_summary(summary, &self.crate_name, Arc::clone(&self.client))
783 }
784
785 fn client_mut(&self) -> Result<&mut BronziteClient> {
786 unsafe {
787 let ptr = Arc::as_ptr(&self.client) as *mut BronziteClient;
788 Ok(&mut *ptr)
789 }
790 }
791}
792
793// ============================================================================
794// Field
795// ============================================================================
796
797/// A field of a struct, enum variant, or union.
798///
799/// Provides field metadata and the ability to navigate to the field's type definition.
800///
801/// # Example
802///
803/// ```ignore
804/// let user = krate.get_struct("User")?;
805/// for field in user.fields()? {
806/// println!("Field: {}", field.name.as_deref().unwrap_or("<unnamed>"));
807/// println!(" Type: {}", field.ty);
808/// println!(" Size: {:?}", field.size);
809///
810/// // Navigate to the field's type definition
811/// if let Some(field_type) = field.type_def()? {
812/// println!(" Defined in: {}", field_type.path());
813/// }
814/// }
815/// ```
816#[derive(Debug, Clone)]
817pub struct Field {
818 /// Field name (None for tuple struct fields)
819 pub name: Option<String>,
820 /// Field index in the struct
821 pub index: usize,
822 /// Type as a string
823 pub ty: String,
824 /// Resolved type (following aliases)
825 pub resolved_ty: Option<String>,
826 /// Field visibility
827 pub visibility: Visibility,
828 /// Doc comments
829 pub docs: Option<String>,
830 /// Offset in bytes (if layout is known)
831 pub offset: Option<usize>,
832 /// Size in bytes (if layout is known)
833 pub size: Option<usize>,
834 crate_name: String,
835 client: Arc<BronziteClient>,
836}
837
838impl Field {
839 fn from_raw(raw: RawFieldInfo, crate_name: &str, client: Arc<BronziteClient>) -> Self {
840 Self {
841 name: raw.name,
842 index: raw.index,
843 ty: raw.ty,
844 resolved_ty: raw.resolved_ty,
845 visibility: raw.visibility,
846 docs: raw.docs,
847 offset: raw.offset,
848 size: raw.size,
849 crate_name: crate_name.to_string(),
850 client,
851 }
852 }
853
854 /// Navigate to the type definition for this field's type.
855 ///
856 /// Returns an [`Item`] representing the field's type definition, if it
857 /// can be resolved. Returns `None` for primitive types or external types
858 /// not in the queried crate.
859 ///
860 /// # Example
861 ///
862 /// ```ignore
863 /// let user = krate.get_struct("User")?;
864 /// for field in user.fields()? {
865 /// if let Some(field_type) = field.type_def()? {
866 /// match field_type {
867 /// Item::Struct(s) => println!("{} is a struct", field.name.unwrap()),
868 /// Item::Enum(e) => println!("{} is an enum", field.name.unwrap()),
869 /// _ => {}
870 /// }
871 /// }
872 /// }
873 /// ```
874 ///
875 /// # Returns
876 ///
877 /// - `Ok(Some(Item))` - The type definition was found
878 /// - `Ok(None)` - The type is primitive or external
879 /// - `Err(_)` - An error occurred querying the daemon
880 pub fn type_def(&self) -> Result<Option<Item>> {
881 let type_path = self.resolved_ty.as_ref().unwrap_or(&self.ty);
882
883 // Try to get type details
884 match self.client_mut()?.get_type(&self.crate_name, type_path) {
885 Ok(details) => {
886 let summary = TypeSummary {
887 name: details.name.clone(),
888 path: details.path.clone(),
889 kind: details.kind.clone(),
890 generics: details.generics.clone(),
891 };
892 Ok(Some(Item::from_summary(
893 summary,
894 &self.crate_name,
895 Arc::clone(&self.client),
896 )?))
897 }
898 Err(_) => Ok(None), // Type might be external or primitive
899 }
900 }
901
902 fn client_mut(&self) -> Result<&mut BronziteClient> {
903 unsafe {
904 let ptr = Arc::as_ptr(&self.client) as *mut BronziteClient;
905 Ok(&mut *ptr)
906 }
907 }
908}
909
910// ============================================================================
911// Trait Implementation
912// ============================================================================
913
914/// A trait implementation block.
915#[derive(Debug, Clone)]
916pub struct TraitImpl {
917 pub trait_path: String,
918 pub generics: Vec<GenericParam>,
919 pub is_unsafe: bool,
920 pub source: Option<String>,
921 raw: RawTraitImpl,
922 crate_name: String,
923 client: Arc<BronziteClient>,
924}
925
926impl TraitImpl {
927 fn from_raw(raw: RawTraitImpl, crate_name: &str, client: Arc<BronziteClient>) -> Self {
928 Self {
929 trait_path: raw.trait_path.clone(),
930 generics: raw.generics.clone(),
931 is_unsafe: raw.is_unsafe,
932 source: raw.source.clone(),
933 raw,
934 crate_name: crate_name.to_string(),
935 client,
936 }
937 }
938
939 /// Navigate to the trait definition being implemented.
940 ///
941 /// Returns the [`TraitDef`] for the trait that this impl block implements.
942 ///
943 /// # Example
944 ///
945 /// ```ignore
946 /// let user = krate.get_struct("User")?;
947 /// for impl_block in user.trait_impls()? {
948 /// let trait_def = impl_block.trait_def()?;
949 /// println!("Implements trait: {}", trait_def.name);
950 /// println!("Trait has {} methods", trait_def.methods().len());
951 /// }
952 /// ```
953 pub fn trait_def(&self) -> Result<TraitDef> {
954 let details = self
955 .client_mut()?
956 .get_trait(&self.crate_name, &self.trait_path)?;
957 TraitDef::from_trait_details(details, &self.crate_name, Arc::clone(&self.client))
958 }
959
960 /// Get methods defined in this impl block.
961 pub fn methods(&self) -> Vec<Method> {
962 self.raw
963 .methods
964 .iter()
965 .map(|m| Method::from_raw(m.clone(), &self.crate_name, Arc::clone(&self.client)))
966 .collect()
967 }
968
969 /// Get associated types in this impl.
970 pub fn associated_types(&self) -> &[AssocTypeInfo] {
971 &self.raw.assoc_types
972 }
973
974 /// Get associated constants in this impl.
975 pub fn associated_consts(&self) -> &[AssocConstInfo] {
976 &self.raw.assoc_consts
977 }
978
979 fn client_mut(&self) -> Result<&mut BronziteClient> {
980 unsafe {
981 let ptr = Arc::as_ptr(&self.client) as *mut BronziteClient;
982 Ok(&mut *ptr)
983 }
984 }
985}
986
987// ============================================================================
988// Method
989// ============================================================================
990
991/// A method (from an impl block).
992///
993/// Provides method metadata including signature, source code, and the ability
994/// to navigate to parameter and return types.
995///
996/// # Example
997///
998/// ```ignore
999/// let user = krate.get_struct("User")?;
1000/// for method in user.methods()? {
1001/// println!("Method: {}", method.name);
1002/// println!(" Signature: {}", method.signature);
1003///
1004/// // Get return type
1005/// if let Some(return_type) = method.return_type_def()? {
1006/// println!(" Returns: {}", return_type.name());
1007/// }
1008///
1009/// // Get method body source
1010/// if let Some(body) = &method.body_source {
1011/// println!(" Body: {}", body);
1012/// }
1013/// }
1014/// ```
1015#[derive(Debug, Clone)]
1016pub struct Method {
1017 /// Method name
1018 pub name: String,
1019 /// Full signature as a string
1020 pub signature: String,
1021 /// Parsed signature components
1022 pub parsed_signature: FunctionSignature,
1023 /// Method body source code (if available)
1024 pub body_source: Option<String>,
1025 /// Whether this is an unsafe method
1026 pub is_unsafe: bool,
1027 /// Whether this is a const method
1028 pub is_const: bool,
1029 /// Whether this is an async method
1030 pub is_async: bool,
1031 /// Doc comments
1032 pub docs: Option<String>,
1033 crate_name: String,
1034 client: Arc<BronziteClient>,
1035}
1036
1037impl Method {
1038 fn from_raw(raw: RawMethodDetails, crate_name: &str, client: Arc<BronziteClient>) -> Self {
1039 Self {
1040 name: raw.name,
1041 signature: raw.signature,
1042 parsed_signature: raw.parsed_signature,
1043 body_source: raw.body_source,
1044 is_unsafe: raw.is_unsafe,
1045 is_const: raw.is_const,
1046 is_async: raw.is_async,
1047 docs: raw.docs,
1048 crate_name: crate_name.to_string(),
1049 client,
1050 }
1051 }
1052
1053 /// Navigate to the return type definition.
1054 ///
1055 /// Returns an [`Item`] representing the method's return type definition,
1056 /// if it can be resolved. Returns `None` if the method returns `()`, or
1057 /// if the type is primitive or external.
1058 ///
1059 /// # Example
1060 ///
1061 /// ```ignore
1062 /// let user = krate.get_struct("User")?;
1063 /// for method in user.methods()? {
1064 /// if let Some(return_type) = method.return_type_def()? {
1065 /// println!("{} returns {}", method.name, return_type.name());
1066 /// }
1067 /// }
1068 /// ```
1069 ///
1070 /// # Returns
1071 ///
1072 /// - `Ok(Some(Item))` - The return type definition was found
1073 /// - `Ok(None)` - No return type, or primitive/external type
1074 /// - `Err(_)` - An error occurred querying the daemon
1075 pub fn return_type_def(&self) -> Result<Option<Item>> {
1076 if let Some(return_ty) = &self.parsed_signature.return_ty {
1077 match self.client_mut()?.get_type(&self.crate_name, return_ty) {
1078 Ok(details) => {
1079 let summary = TypeSummary {
1080 name: details.name.clone(),
1081 path: details.path.clone(),
1082 kind: details.kind.clone(),
1083 generics: details.generics.clone(),
1084 };
1085 Ok(Some(Item::from_summary(
1086 summary,
1087 &self.crate_name,
1088 Arc::clone(&self.client),
1089 )?))
1090 }
1091 Err(_) => Ok(None),
1092 }
1093 } else {
1094 Ok(None)
1095 }
1096 }
1097
1098 /// Navigate to parameter type definitions.
1099 ///
1100 /// Returns a vector of optional [`Item`]s, one for each parameter.
1101 /// Each entry is `Some(Item)` if the type can be resolved, or `None`
1102 /// for primitive/external types.
1103 ///
1104 /// # Example
1105 ///
1106 /// ```ignore
1107 /// let user = krate.get_struct("User")?;
1108 /// for method in user.methods()? {
1109 /// println!("Method: {}", method.name);
1110 /// for (i, param_type) in method.param_types()?.into_iter().enumerate() {
1111 /// if let Some(ptype) = param_type {
1112 /// println!(" Param {}: {}", i, ptype.name());
1113 /// }
1114 /// }
1115 /// }
1116 /// ```
1117 ///
1118 /// # Returns
1119 ///
1120 /// A vector where each element corresponds to a parameter:
1121 /// - `Some(Item)` - The parameter type was found
1122 /// - `None` - The type is primitive or external
1123 pub fn param_types(&self) -> Result<Vec<Option<Item>>> {
1124 self.parsed_signature
1125 .params
1126 .iter()
1127 .map(
1128 |param| match self.client_mut()?.get_type(&self.crate_name, ¶m.ty) {
1129 Ok(details) => {
1130 let summary = TypeSummary {
1131 name: details.name.clone(),
1132 path: details.path.clone(),
1133 kind: details.kind.clone(),
1134 generics: details.generics.clone(),
1135 };
1136 Ok(Some(Item::from_summary(
1137 summary,
1138 &self.crate_name,
1139 Arc::clone(&self.client),
1140 )?))
1141 }
1142 Err(_) => Ok(None),
1143 },
1144 )
1145 .collect()
1146 }
1147
1148 fn client_mut(&self) -> Result<&mut BronziteClient> {
1149 unsafe {
1150 let ptr = Arc::as_ptr(&self.client) as *mut BronziteClient;
1151 Ok(&mut *ptr)
1152 }
1153 }
1154}