use crate::{BronziteClient, Error, Result};
use bronzite_types::{
AssocConstInfo, AssocTypeInfo, FieldInfo as RawFieldInfo, FunctionSignature, GenericParam,
LayoutInfo, MethodDetails as RawMethodDetails, TraitDetails as RawTraitDetails,
TraitImplDetails as RawTraitImpl, TypeDetails, TypeSummary, Visibility,
};
use std::sync::Arc;
pub struct Crate {
name: String,
client: Arc<BronziteClient>,
}
impl Crate {
pub fn reflect(crate_name: impl Into<String>) -> Result<Self> {
crate::ensure_daemon_running(None)?;
let client = crate::connect()?;
Ok(Self {
name: crate_name.into(),
client: Arc::new(client),
})
}
pub fn name(&self) -> &str {
&self.name
}
pub fn items(&self, pattern: &str) -> Result<Vec<Item>> {
let types = self.client_mut()?.find_types(&self.name, pattern)?;
types
.into_iter()
.map(|summary| Item::from_summary(summary, &self.name, Arc::clone(&self.client)))
.collect()
}
pub fn structs(&self, pattern: &str) -> Result<Vec<StructDef>> {
let items = self.items(pattern)?;
Ok(items
.into_iter()
.filter_map(|item| match item {
Item::Struct(s) => Some(s),
_ => None,
})
.collect())
}
pub fn enums(&self, pattern: &str) -> Result<Vec<EnumDef>> {
let items = self.items(pattern)?;
Ok(items
.into_iter()
.filter_map(|item| match item {
Item::Enum(e) => Some(e),
_ => None,
})
.collect())
}
pub fn traits(&self, pattern: &str) -> Result<Vec<TraitDef>> {
let all_traits = self.client_mut()?.get_traits(&self.name)?;
let matching: Vec<_> = all_traits
.into_iter()
.filter(|t| bronzite_types::path_matches_pattern(&t.path, pattern))
.collect();
matching
.into_iter()
.map(|info| TraitDef::from_info(info, &self.name, Arc::clone(&self.client)))
.collect()
}
pub fn get_struct(&self, path: &str) -> Result<StructDef> {
let details = self.client_mut()?.get_type(&self.name, path)?;
StructDef::from_details(details, &self.name, Arc::clone(&self.client))
}
pub fn get_enum(&self, path: &str) -> Result<EnumDef> {
let details = self.client_mut()?.get_type(&self.name, path)?;
EnumDef::from_details(details, &self.name, Arc::clone(&self.client))
}
pub fn get_trait(&self, path: &str) -> Result<TraitDef> {
let details = self.client_mut()?.get_trait(&self.name, path)?;
TraitDef::from_trait_details(details, &self.name, Arc::clone(&self.client))
}
pub fn get_type_alias(&self, path: &str) -> Result<TypeAliasDef> {
let (original, resolved, chain) = self.client_mut()?.resolve_alias(&self.name, path)?;
Ok(TypeAliasDef {
path: original,
resolved_path: resolved,
resolution_chain: chain,
crate_name: self.name.clone(),
client: Arc::clone(&self.client),
})
}
fn client_mut(&self) -> Result<&mut BronziteClient> {
unsafe {
let ptr = Arc::as_ptr(&self.client) as *mut BronziteClient;
Ok(&mut *ptr)
}
}
}
#[derive(Debug, Clone)]
pub enum Item {
Struct(StructDef),
Enum(EnumDef),
Trait(TraitDef),
TypeAlias(TypeAliasDef),
Union(UnionDef),
}
impl Item {
pub fn name(&self) -> &str {
match self {
Item::Struct(s) => &s.name,
Item::Enum(e) => &e.name,
Item::Trait(t) => &t.name,
Item::TypeAlias(a) => &a.path,
Item::Union(u) => &u.name,
}
}
pub fn path(&self) -> &str {
match self {
Item::Struct(s) => &s.path,
Item::Enum(e) => &e.path,
Item::Trait(t) => &t.path,
Item::TypeAlias(a) => &a.path,
Item::Union(u) => &u.path,
}
}
fn from_summary(
summary: TypeSummary,
crate_name: &str,
client: Arc<BronziteClient>,
) -> Result<Self> {
match summary.kind {
bronzite_types::TypeKind::Struct => Ok(Item::Struct(StructDef {
name: summary.name,
path: summary.path,
generics: summary.generics,
crate_name: crate_name.to_string(),
client,
cached_details: None,
})),
bronzite_types::TypeKind::Enum => Ok(Item::Enum(EnumDef {
name: summary.name,
path: summary.path,
generics: summary.generics,
crate_name: crate_name.to_string(),
client,
cached_details: None,
})),
bronzite_types::TypeKind::Union => Ok(Item::Union(UnionDef {
name: summary.name,
path: summary.path,
generics: summary.generics,
crate_name: crate_name.to_string(),
client,
})),
bronzite_types::TypeKind::Trait => {
let client_mut = unsafe {
let ptr = Arc::as_ptr(&client) as *mut BronziteClient;
&mut *ptr
};
let details = client_mut.get_trait(crate_name, &summary.path)?;
Ok(Item::Trait(TraitDef::from_trait_details(
details, crate_name, client,
)?))
}
_ => Err(Error::UnexpectedResponse),
}
}
}
#[derive(Debug, Clone)]
pub struct StructDef {
pub name: String,
pub path: String,
pub generics: Vec<GenericParam>,
crate_name: String,
client: Arc<BronziteClient>,
cached_details: Option<Box<TypeDetails>>,
}
impl StructDef {
fn from_details(
details: TypeDetails,
crate_name: &str,
client: Arc<BronziteClient>,
) -> Result<Self> {
Ok(Self {
name: details.name.clone(),
path: details.path.clone(),
generics: details.generics.clone(),
crate_name: crate_name.to_string(),
client,
cached_details: Some(Box::new(details)),
})
}
pub fn fields(&self) -> Result<Vec<Field>> {
let fields = self
.client_mut()?
.get_fields(&self.crate_name, &self.path)?;
Ok(fields
.into_iter()
.map(|f| Field::from_raw(f, &self.crate_name, Arc::clone(&self.client)))
.collect())
}
pub fn trait_impls(&self) -> Result<Vec<TraitImpl>> {
let impls = self
.client_mut()?
.get_trait_impls(&self.crate_name, &self.path)?;
Ok(impls
.into_iter()
.map(|i| TraitImpl::from_raw(i, &self.crate_name, Arc::clone(&self.client)))
.collect())
}
pub fn implements(&self, trait_path: &str) -> Result<bool> {
let (implements, _) =
self.client_mut()?
.check_impl(&self.crate_name, &self.path, trait_path)?;
Ok(implements)
}
pub fn methods(&self) -> Result<Vec<Method>> {
let impls = self
.client_mut()?
.get_inherent_impls(&self.crate_name, &self.path)?;
Ok(impls
.into_iter()
.flat_map(|impl_block| {
impl_block
.methods
.into_iter()
.map(|m| Method::from_raw(m, &self.crate_name, Arc::clone(&self.client)))
})
.collect())
}
pub fn layout(&self) -> Result<LayoutInfo> {
self.client_mut()?.get_layout(&self.crate_name, &self.path)
}
pub fn source(&self) -> Option<&str> {
self.details().and_then(|d| d.source.as_deref())
}
pub fn details(&self) -> Option<&TypeDetails> {
self.cached_details.as_deref()
}
pub fn visibility(&self) -> Option<&Visibility> {
self.details().map(|d| &d.visibility)
}
pub fn docs(&self) -> Option<&str> {
self.details().and_then(|d| d.docs.as_deref())
}
fn client_mut(&self) -> Result<&mut BronziteClient> {
unsafe {
let ptr = Arc::as_ptr(&self.client) as *mut BronziteClient;
Ok(&mut *ptr)
}
}
}
#[derive(Debug, Clone)]
pub struct EnumDef {
pub name: String,
pub path: String,
pub generics: Vec<GenericParam>,
crate_name: String,
client: Arc<BronziteClient>,
cached_details: Option<Box<TypeDetails>>,
}
impl EnumDef {
fn from_details(
details: TypeDetails,
crate_name: &str,
client: Arc<BronziteClient>,
) -> Result<Self> {
Ok(Self {
name: details.name.clone(),
path: details.path.clone(),
generics: details.generics.clone(),
crate_name: crate_name.to_string(),
client,
cached_details: Some(Box::new(details)),
})
}
pub fn variants(&self) -> Option<&[bronzite_types::EnumVariantInfo]> {
self.details().and_then(|d| d.variants.as_deref())
}
pub fn trait_impls(&self) -> Result<Vec<TraitImpl>> {
let impls = self
.client_mut()?
.get_trait_impls(&self.crate_name, &self.path)?;
Ok(impls
.into_iter()
.map(|i| TraitImpl::from_raw(i, &self.crate_name, Arc::clone(&self.client)))
.collect())
}
pub fn implements(&self, trait_path: &str) -> Result<bool> {
let (implements, _) =
self.client_mut()?
.check_impl(&self.crate_name, &self.path, trait_path)?;
Ok(implements)
}
pub fn methods(&self) -> Result<Vec<Method>> {
let impls = self
.client_mut()?
.get_inherent_impls(&self.crate_name, &self.path)?;
Ok(impls
.into_iter()
.flat_map(|impl_block| {
impl_block
.methods
.into_iter()
.map(|m| Method::from_raw(m, &self.crate_name, Arc::clone(&self.client)))
})
.collect())
}
pub fn source(&self) -> Option<&str> {
self.details().and_then(|d| d.source.as_deref())
}
pub fn details(&self) -> Option<&TypeDetails> {
self.cached_details.as_deref()
}
pub fn visibility(&self) -> Option<&Visibility> {
self.details().map(|d| &d.visibility)
}
pub fn docs(&self) -> Option<&str> {
self.details().and_then(|d| d.docs.as_deref())
}
fn client_mut(&self) -> Result<&mut BronziteClient> {
unsafe {
let ptr = Arc::as_ptr(&self.client) as *mut BronziteClient;
Ok(&mut *ptr)
}
}
}
#[derive(Debug, Clone)]
pub struct UnionDef {
pub name: String,
pub path: String,
pub generics: Vec<GenericParam>,
crate_name: String,
client: Arc<BronziteClient>,
}
impl UnionDef {
pub fn fields(&self) -> Result<Vec<Field>> {
let fields = self
.client_mut()?
.get_fields(&self.crate_name, &self.path)?;
Ok(fields
.into_iter()
.map(|f| Field::from_raw(f, &self.crate_name, Arc::clone(&self.client)))
.collect())
}
fn client_mut(&self) -> Result<&mut BronziteClient> {
unsafe {
let ptr = Arc::as_ptr(&self.client) as *mut BronziteClient;
Ok(&mut *ptr)
}
}
}
#[derive(Debug, Clone)]
pub struct TraitDef {
pub name: String,
pub path: String,
pub generics: Vec<GenericParam>,
pub is_auto: bool,
pub is_unsafe: bool,
pub supertraits: Vec<String>,
pub source: Option<String>,
pub docs: Option<String>,
crate_name: String,
client: Arc<BronziteClient>,
cached_details: Option<Box<RawTraitDetails>>,
}
impl TraitDef {
fn from_info(
info: bronzite_types::TraitInfo,
crate_name: &str,
client: Arc<BronziteClient>,
) -> Result<Self> {
let client_mut = unsafe {
let ptr = Arc::as_ptr(&client) as *mut BronziteClient;
&mut *ptr
};
let details = client_mut.get_trait(crate_name, &info.path)?;
Self::from_trait_details(details, crate_name, client)
}
fn from_trait_details(
details: RawTraitDetails,
crate_name: &str,
client: Arc<BronziteClient>,
) -> Result<Self> {
Ok(Self {
name: details.name.clone(),
path: details.path.clone(),
generics: details.generics.clone(),
is_auto: details.is_auto,
is_unsafe: details.is_unsafe,
supertraits: details.supertraits.clone(),
source: details.source.clone(),
docs: details.docs.clone(),
crate_name: crate_name.to_string(),
client,
cached_details: Some(Box::new(details)),
})
}
pub fn methods(&self) -> Vec<TraitMethod> {
self.cached_details
.as_ref()
.map(|d| {
d.methods
.iter()
.map(|m| TraitMethod {
name: m.name.clone(),
signature: m.signature.clone(),
parsed_signature: m.parsed_signature.clone(),
has_default: m.has_default,
default_body: m.default_body.clone(),
is_unsafe: m.is_unsafe,
docs: m.docs.clone(),
})
.collect()
})
.unwrap_or_default()
}
pub fn associated_types(&self) -> Vec<&AssocTypeInfo> {
self.cached_details
.as_ref()
.map(|d| d.assoc_types.iter().collect())
.unwrap_or_default()
}
pub fn associated_consts(&self) -> Vec<&AssocConstInfo> {
self.cached_details
.as_ref()
.map(|d| d.assoc_consts.iter().collect())
.unwrap_or_default()
}
pub fn implementors(&self) -> Result<Vec<Item>> {
let types = self
.client_mut()?
.get_implementors(&self.crate_name, &self.path)?;
types
.into_iter()
.map(|summary| Item::from_summary(summary, &self.crate_name, Arc::clone(&self.client)))
.collect()
}
fn client_mut(&self) -> Result<&mut BronziteClient> {
unsafe {
let ptr = Arc::as_ptr(&self.client) as *mut BronziteClient;
Ok(&mut *ptr)
}
}
}
#[derive(Debug, Clone)]
pub struct TraitMethod {
pub name: String,
pub signature: String,
pub parsed_signature: FunctionSignature,
pub has_default: bool,
pub default_body: Option<String>,
pub is_unsafe: bool,
pub docs: Option<String>,
}
#[derive(Debug, Clone)]
pub struct TypeAliasDef {
pub path: String,
pub resolved_path: String,
pub resolution_chain: Vec<String>,
crate_name: String,
client: Arc<BronziteClient>,
}
impl TypeAliasDef {
pub fn resolve(&self) -> Result<Item> {
let details = self
.client_mut()?
.get_type(&self.crate_name, &self.resolved_path)?;
let summary = TypeSummary {
name: details.name.clone(),
path: details.path.clone(),
kind: details.kind.clone(),
generics: details.generics.clone(),
};
Item::from_summary(summary, &self.crate_name, Arc::clone(&self.client))
}
fn client_mut(&self) -> Result<&mut BronziteClient> {
unsafe {
let ptr = Arc::as_ptr(&self.client) as *mut BronziteClient;
Ok(&mut *ptr)
}
}
}
#[derive(Debug, Clone)]
pub struct Field {
pub name: Option<String>,
pub index: usize,
pub ty: String,
pub resolved_ty: Option<String>,
pub visibility: Visibility,
pub docs: Option<String>,
pub offset: Option<usize>,
pub size: Option<usize>,
crate_name: String,
client: Arc<BronziteClient>,
}
impl Field {
fn from_raw(raw: RawFieldInfo, crate_name: &str, client: Arc<BronziteClient>) -> Self {
Self {
name: raw.name,
index: raw.index,
ty: raw.ty,
resolved_ty: raw.resolved_ty,
visibility: raw.visibility,
docs: raw.docs,
offset: raw.offset,
size: raw.size,
crate_name: crate_name.to_string(),
client,
}
}
pub fn type_def(&self) -> Result<Option<Item>> {
let type_path = self.resolved_ty.as_ref().unwrap_or(&self.ty);
match self.client_mut()?.get_type(&self.crate_name, type_path) {
Ok(details) => {
let summary = TypeSummary {
name: details.name.clone(),
path: details.path.clone(),
kind: details.kind.clone(),
generics: details.generics.clone(),
};
Ok(Some(Item::from_summary(
summary,
&self.crate_name,
Arc::clone(&self.client),
)?))
}
Err(_) => Ok(None), }
}
fn client_mut(&self) -> Result<&mut BronziteClient> {
unsafe {
let ptr = Arc::as_ptr(&self.client) as *mut BronziteClient;
Ok(&mut *ptr)
}
}
}
#[derive(Debug, Clone)]
pub struct TraitImpl {
pub trait_path: String,
pub generics: Vec<GenericParam>,
pub is_unsafe: bool,
pub source: Option<String>,
raw: RawTraitImpl,
crate_name: String,
client: Arc<BronziteClient>,
}
impl TraitImpl {
fn from_raw(raw: RawTraitImpl, crate_name: &str, client: Arc<BronziteClient>) -> Self {
Self {
trait_path: raw.trait_path.clone(),
generics: raw.generics.clone(),
is_unsafe: raw.is_unsafe,
source: raw.source.clone(),
raw,
crate_name: crate_name.to_string(),
client,
}
}
pub fn trait_def(&self) -> Result<TraitDef> {
let details = self
.client_mut()?
.get_trait(&self.crate_name, &self.trait_path)?;
TraitDef::from_trait_details(details, &self.crate_name, Arc::clone(&self.client))
}
pub fn methods(&self) -> Vec<Method> {
self.raw
.methods
.iter()
.map(|m| Method::from_raw(m.clone(), &self.crate_name, Arc::clone(&self.client)))
.collect()
}
pub fn associated_types(&self) -> &[AssocTypeInfo] {
&self.raw.assoc_types
}
pub fn associated_consts(&self) -> &[AssocConstInfo] {
&self.raw.assoc_consts
}
fn client_mut(&self) -> Result<&mut BronziteClient> {
unsafe {
let ptr = Arc::as_ptr(&self.client) as *mut BronziteClient;
Ok(&mut *ptr)
}
}
}
#[derive(Debug, Clone)]
pub struct Method {
pub name: String,
pub signature: String,
pub parsed_signature: FunctionSignature,
pub body_source: Option<String>,
pub is_unsafe: bool,
pub is_const: bool,
pub is_async: bool,
pub docs: Option<String>,
crate_name: String,
client: Arc<BronziteClient>,
}
impl Method {
fn from_raw(raw: RawMethodDetails, crate_name: &str, client: Arc<BronziteClient>) -> Self {
Self {
name: raw.name,
signature: raw.signature,
parsed_signature: raw.parsed_signature,
body_source: raw.body_source,
is_unsafe: raw.is_unsafe,
is_const: raw.is_const,
is_async: raw.is_async,
docs: raw.docs,
crate_name: crate_name.to_string(),
client,
}
}
pub fn return_type_def(&self) -> Result<Option<Item>> {
if let Some(return_ty) = &self.parsed_signature.return_ty {
match self.client_mut()?.get_type(&self.crate_name, return_ty) {
Ok(details) => {
let summary = TypeSummary {
name: details.name.clone(),
path: details.path.clone(),
kind: details.kind.clone(),
generics: details.generics.clone(),
};
Ok(Some(Item::from_summary(
summary,
&self.crate_name,
Arc::clone(&self.client),
)?))
}
Err(_) => Ok(None),
}
} else {
Ok(None)
}
}
pub fn param_types(&self) -> Result<Vec<Option<Item>>> {
self.parsed_signature
.params
.iter()
.map(
|param| match self.client_mut()?.get_type(&self.crate_name, ¶m.ty) {
Ok(details) => {
let summary = TypeSummary {
name: details.name.clone(),
path: details.path.clone(),
kind: details.kind.clone(),
generics: details.generics.clone(),
};
Ok(Some(Item::from_summary(
summary,
&self.crate_name,
Arc::clone(&self.client),
)?))
}
Err(_) => Ok(None),
},
)
.collect()
}
fn client_mut(&self) -> Result<&mut BronziteClient> {
unsafe {
let ptr = Arc::as_ptr(&self.client) as *mut BronziteClient;
Ok(&mut *ptr)
}
}
}