use std::collections::{HashMap, HashSet};
use std::fmt::{self, Display};
use std::path::PathBuf;
use serde::{de, Deserialize, Deserializer, Serialize};
use crate::query::Qualifier;
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, bincode::Decode, bincode::Encode)]
pub struct Crate {
pub name: Option<String>,
pub root: Id,
#[serde(
serialize_with = "crate_version_as_string",
deserialize_with = "crate_version_from_string"
)]
pub crate_version: String, pub includes_private: bool,
pub index: HashMap<Id, Item>,
pub paths: HashMap<Id, ItemSummary>,
pub external_crates: HashMap<u32, ExternalCrate>,
pub target: Target,
pub format_version: u32,
}
fn crate_version_as_string<S>(version: &String, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_some(version)
}
fn crate_version_from_string<'de, D>(deserializer: D) -> Result<String, D::Error>
where
D: Deserializer<'de>,
{
let opt: Option<String> = Option::deserialize(deserializer)?;
Ok(opt.unwrap_or("latest".to_string()))
}
#[derive(Debug, Clone, Deserialize, Serialize, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct CrateMetadata {
pub name: String,
pub version: String,
}
impl CrateMetadata {
pub fn new(name: String) -> Self {
CrateMetadata {
name,
version: "latest".to_string(),
}
}
}
impl std::fmt::Display for CrateMetadata {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}:{}", self.name, self.version)
}
}
impl Crate {
pub fn crate_metadata(&self) -> CrateMetadata {
CrateMetadata {
name: self
.name
.clone()
.expect("`.crate_metadata` SHOULD NEVER be called on anonymous crates"),
version: self.crate_version.clone(),
}
}
}
#[derive(
Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default, bincode::Decode, bincode::Encode,
)]
pub struct Target {
pub triple: String,
pub target_features: Vec<TargetFeature>,
}
#[derive(
Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default, bincode::Decode, bincode::Encode,
)]
pub struct TargetFeature {
pub name: String,
pub implies_features: Vec<String>,
pub unstable_feature_gate: Option<String>,
pub globally_enabled: bool,
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
pub struct ExternalCrate {
pub name: String,
pub html_root_url: Option<String>,
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
pub struct ItemSummary {
pub crate_id: u32,
pub path: Vec<String>,
pub kind: ItemKind,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, bincode::Decode, bincode::Encode)]
pub struct Item {
pub id: Id,
pub crate_id: u32,
pub name: Option<String>,
pub span: Option<Span>,
pub visibility: Visibility,
pub docs: Option<String>,
pub links: HashMap<String, Id>,
pub attrs: Vec<Attribute>,
pub deprecation: Option<Deprecation>,
pub inner: ItemEnum,
}
impl Display for Item {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(name) = &self.name {
write!(f, "{} ", name)?;
}
write!(f, "{}", self.inner)
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, bincode::Decode, bincode::Encode)]
#[serde(rename_all = "snake_case")]
pub enum Attribute {
NonExhaustive,
MustUse { reason: Option<String> },
MacroExport,
ExportName(String),
LinkSection(String),
AutomaticallyDerived,
Repr(AttributeRepr),
NoMangle,
TargetFeature { enable: Vec<String> },
Other(String),
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, bincode::Decode, bincode::Encode)]
pub struct AttributeRepr {
pub kind: ReprKind,
pub align: Option<u64>,
pub packed: Option<u64>,
pub int: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, bincode::Decode, bincode::Encode)]
#[serde(rename_all = "snake_case")]
pub enum ReprKind {
Rust,
C,
Transparent,
Simd,
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
pub struct Span {
pub filename: PathBuf,
pub begin: (usize, usize),
pub end: (usize, usize),
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
pub struct Deprecation {
pub since: Option<String>,
pub note: Option<String>,
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
#[serde(rename_all = "snake_case")]
pub enum Visibility {
Public,
Default,
Crate,
Restricted {
parent: Id,
path: String,
},
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
pub struct DynTrait {
pub traits: Vec<PolyTrait>,
pub lifetime: Option<String>,
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
pub struct PolyTrait {
#[serde(rename = "trait")]
pub trait_: Path,
pub generic_params: Vec<GenericParamDef>,
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
#[serde(rename_all = "snake_case")]
pub enum GenericArgs {
AngleBracketed {
args: Vec<GenericArg>,
constraints: Vec<AssocItemConstraint>,
},
Parenthesized {
inputs: Vec<Type>,
output: Option<Type>,
},
ReturnTypeNotation,
}
impl Display for GenericArgs {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
GenericArgs::AngleBracketed { args, constraints } => {
write!(f, "<")?;
for (i, arg) in args.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{}", arg)?;
}
for constraint in constraints {
write!(f, ", {} ", constraint.name)?;
match &constraint.binding {
AssocItemConstraintKind::Equality(term) => {
write!(f, "= {}", term)?;
}
AssocItemConstraintKind::Constraint(bounds) => {
write!(f, ": ")?;
for (i, bound) in bounds.iter().enumerate() {
if i > 0 {
write!(f, " + ")?;
}
write!(f, "{}", bound)?;
}
}
}
}
write!(f, ">")
}
GenericArgs::Parenthesized { inputs, output } => {
write!(f, "(")?;
for (i, input) in inputs.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{}", input)?;
}
write!(f, ")")?;
if let Some(output) = output {
write!(f, " -> {}", output)?;
}
Ok(())
}
GenericArgs::ReturnTypeNotation => write!(f, "..."),
}
}
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
#[serde(rename_all = "snake_case")]
pub enum GenericArg {
Lifetime(String),
Type(Type),
Const(Constant),
Infer,
}
impl Display for GenericArg {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
GenericArg::Lifetime(l) => write!(f, "{}", l),
GenericArg::Type(t) => write!(f, "{}", t),
GenericArg::Const(c) => write!(f, "{}", c),
GenericArg::Infer => write!(f, "_"),
}
}
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
pub struct Constant {
pub expr: String,
pub value: Option<String>,
pub is_literal: bool,
}
impl Display for Constant {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.expr)
}
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
pub struct AssocItemConstraint {
pub name: String,
pub args: Option<Box<GenericArgs>>,
pub binding: AssocItemConstraintKind,
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
#[serde(rename_all = "snake_case")]
pub enum AssocItemConstraintKind {
Equality(Term),
Constraint(Vec<GenericBound>),
}
#[derive(
Clone,
Copy,
Debug,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
Serialize,
bincode::Decode,
bincode::Encode,
)]
pub struct Id(pub u32);
impl<'de> Deserialize<'de> for Id {
fn deserialize<D>(de: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct IdVisitor;
impl<'de> de::Visitor<'de> for IdVisitor {
type Value = Id;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("a u32 or a string containing a decimal u32")
}
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
where
E: de::Error,
{
u32::try_from(v)
.map(Id)
.map_err(|_| E::invalid_value(de::Unexpected::Unsigned(v), &"u32 in range"))
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
let s = s.trim();
let s = s.replace('_', "");
s.parse::<u32>()
.map(Id)
.map_err(|_| E::invalid_value(de::Unexpected::Str(&s), &"decimal u32 string"))
}
fn visit_string<E>(self, s: String) -> Result<Self::Value, E>
where
E: de::Error,
{
self.visit_str(&s)
}
}
de.deserialize_any(IdVisitor)
}
}
#[derive(
Clone,
Copy,
Debug,
PartialEq,
Eq,
Hash,
Serialize,
Deserialize,
bincode::Decode,
bincode::Encode,
)]
#[serde(rename_all = "snake_case")]
pub enum ItemKind {
Module,
ExternCrate,
Use,
Struct,
StructField,
Union,
Enum,
Variant,
Function,
TypeAlias,
Constant,
Trait,
TraitAlias,
Impl,
Static,
ExternType,
Macro,
ProcAttribute,
ProcDerive,
AssocConst,
AssocType,
Primitive,
Keyword,
Attribute,
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
#[serde(rename_all = "snake_case")]
pub enum ItemEnum {
Module(Module),
ExternCrate {
name: String,
rename: Option<String>,
},
Use(Use),
Union(Union),
Struct(Struct),
StructField(Type),
Enum(Enum),
Variant(Variant),
Function(Function),
Trait(Trait),
TraitAlias(TraitAlias),
Impl(Impl),
TypeAlias(TypeAlias),
Constant {
#[serde(rename = "type")]
type_: Type,
#[serde(rename = "const")]
const_: Constant,
},
Static(Static),
ExternType,
Macro(String),
ProcMacro(ProcMacro),
Primitive(Primitive),
AssocConst {
#[serde(rename = "type")]
type_: Type,
value: Option<String>,
},
AssocType {
generics: Generics,
bounds: Vec<GenericBound>,
#[serde(rename = "type")]
type_: Option<Type>,
},
}
impl Display for ItemEnum {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ItemEnum::Module(_) => write!(f, "module"),
ItemEnum::ExternCrate { .. } => write!(f, "extern crate"),
ItemEnum::Use(_) => write!(f, "use"),
ItemEnum::Union(_) => write!(f, "union"),
ItemEnum::Struct(_) => write!(f, "struct"),
ItemEnum::StructField(_) => write!(f, "struct field"),
ItemEnum::Enum(_) => write!(f, "enum"),
ItemEnum::Variant(_) => write!(f, "variant"),
ItemEnum::Function(f_) => write!(f, "{}", f_),
ItemEnum::Trait(_) => write!(f, "trait"),
ItemEnum::TraitAlias(_) => write!(f, "trait alias"),
ItemEnum::Impl(_) => write!(f, "impl"),
ItemEnum::TypeAlias(_) => write!(f, "type alias"),
ItemEnum::Constant { .. } => write!(f, "constant"),
ItemEnum::Static(_) => write!(f, "static"),
ItemEnum::ExternType => write!(f, "extern type"),
ItemEnum::Macro(_) => write!(f, "macro"),
ItemEnum::ProcMacro(_) => write!(f, "procedural macro"),
ItemEnum::Primitive(_) => write!(f, "primitive type"),
ItemEnum::AssocConst { .. } => write!(f, "associated constant"),
ItemEnum::AssocType { .. } => write!(f, "associated type"),
}
}
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
pub struct Module {
pub is_crate: bool,
pub items: Vec<Id>,
pub is_stripped: bool,
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
pub struct Union {
pub generics: Generics,
pub has_stripped_fields: bool,
pub fields: Vec<Id>,
pub impls: Vec<Id>,
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
pub struct Struct {
pub kind: StructKind,
pub generics: Generics,
pub impls: Vec<Id>,
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
#[serde(rename_all = "snake_case")]
pub enum StructKind {
Unit,
Tuple(Vec<Option<Id>>),
Plain {
fields: Vec<Id>,
has_stripped_fields: bool,
},
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
pub struct Enum {
pub generics: Generics,
pub has_stripped_variants: bool,
pub variants: Vec<Id>,
pub impls: Vec<Id>,
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
pub struct Variant {
pub kind: VariantKind,
pub discriminant: Option<Discriminant>,
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
#[serde(rename_all = "snake_case")]
pub enum VariantKind {
Plain,
Tuple(Vec<Option<Id>>),
Struct {
fields: Vec<Id>,
has_stripped_fields: bool,
},
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
pub struct Discriminant {
pub expr: String,
pub value: String,
}
#[derive(
Clone,
Debug,
PartialEq,
Eq,
Hash,
Default,
Serialize,
Deserialize,
bincode::Decode,
bincode::Encode,
)]
pub struct FunctionHeader {
pub is_const: bool,
pub is_unsafe: bool,
pub is_async: bool,
pub abi: Abi,
}
impl Display for FunctionHeader {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.is_const {
write!(f, " const")?;
}
if self.is_unsafe {
write!(f, " unsafe")?;
}
if self.is_async {
write!(f, " async")?;
}
Ok(())
}
}
impl FunctionHeader {
pub fn qualifiers(&self) -> HashSet<Qualifier> {
let mut quals = HashSet::new();
if self.is_const {
quals.insert(Qualifier::Const);
}
if self.is_unsafe {
quals.insert(Qualifier::Unsafe);
}
if self.is_async {
quals.insert(Qualifier::Async);
}
quals
}
}
#[derive(
Clone,
Debug,
PartialEq,
Eq,
Hash,
Default,
Serialize,
Deserialize,
bincode::Decode,
bincode::Encode,
)]
pub enum Abi {
#[default]
Rust,
C { unwind: bool },
Cdecl { unwind: bool },
Stdcall { unwind: bool },
Fastcall { unwind: bool },
Aapcs { unwind: bool },
Win64 { unwind: bool },
SysV64 { unwind: bool },
System { unwind: bool },
Other(String),
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
pub struct Function {
pub sig: FunctionSignature,
pub generics: Generics,
pub header: FunctionHeader,
pub has_body: bool,
}
impl Display for Function {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} {} {}", self.header, self.generics, self.sig)
}
}
#[derive(
Clone,
Debug,
PartialEq,
Eq,
Hash,
Default,
Serialize,
Deserialize,
bincode::Decode,
bincode::Encode,
)]
pub struct Generics {
pub params: Vec<GenericParamDef>,
pub where_predicates: Vec<WherePredicate>,
}
impl Display for Generics {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if !self.params.is_empty() {
write!(
f,
"<{}>",
self.params
.iter()
.map(|p| p.to_string())
.collect::<Vec<_>>()
.join(", ")
)?;
}
if !self.where_predicates.is_empty() {
write!(
f,
" where {}",
self.where_predicates
.iter()
.map(|p| p.to_string())
.collect::<Vec<_>>()
.join(", ")
)?;
}
Ok(())
}
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
pub struct GenericParamDef {
pub name: String,
pub kind: GenericParamDefKind,
}
impl Display for GenericParamDef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.kind {
GenericParamDefKind::Lifetime { outlives } => {
write!(f, "{}", self.name)?;
if !outlives.is_empty() {
write!(f, ": {}", outlives.join(" + "))?;
}
Ok(())
}
GenericParamDefKind::Type {
bounds,
default,
is_synthetic,
} => {
if *is_synthetic {
write!(
f,
"impl {}",
bounds
.iter()
.map(|b| b.to_string())
.collect::<Vec<_>>()
.join(" + ")
)?;
} else {
write!(f, "{}", self.name)?;
if !bounds.is_empty() {
write!(
f,
": {}",
bounds
.iter()
.map(|b| b.to_string())
.collect::<Vec<_>>()
.join(" + ")
)?;
}
}
if let Some(default) = default {
write!(f, " = {}", default)?;
}
Ok(())
}
GenericParamDefKind::Const { type_, default } => {
write!(f, "const {}: {}", self.name, type_)?;
if let Some(default) = default {
write!(f, " = {}", default)?;
}
Ok(())
}
}
}
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
#[serde(rename_all = "snake_case")]
pub enum GenericParamDefKind {
Lifetime {
outlives: Vec<String>,
},
Type {
bounds: Vec<GenericBound>,
default: Option<Type>,
is_synthetic: bool,
},
Const {
#[serde(rename = "type")]
type_: Type,
default: Option<String>,
},
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
#[serde(rename_all = "snake_case")]
pub enum WherePredicate {
BoundPredicate {
#[serde(rename = "type")]
type_: Type,
bounds: Vec<GenericBound>,
generic_params: Vec<GenericParamDef>,
},
LifetimePredicate {
lifetime: String,
outlives: Vec<String>,
},
EqPredicate {
lhs: Type,
rhs: Term,
},
}
impl Display for WherePredicate {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
WherePredicate::BoundPredicate {
type_,
bounds,
generic_params,
} => {
if !generic_params.is_empty() {
write!(
f,
"for<{}> ",
generic_params
.iter()
.map(|p| p.to_string())
.collect::<Vec<_>>()
.join(", ")
)?;
}
write!(
f,
"{}: {}",
type_,
bounds
.iter()
.map(|b| b.to_string())
.collect::<Vec<_>>()
.join(" + ")
)
}
WherePredicate::LifetimePredicate { lifetime, outlives } => {
write!(f, "{}: {}", lifetime, outlives.join(" + "))
}
WherePredicate::EqPredicate { lhs, rhs } => {
write!(f, "{} = {}", lhs, rhs)
}
}
}
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
#[serde(rename_all = "snake_case")]
pub enum GenericBound {
TraitBound {
#[serde(rename = "trait")]
trait_: Path,
generic_params: Vec<GenericParamDef>,
modifier: TraitBoundModifier,
},
Outlives(String),
Use(Vec<PreciseCapturingArg>),
}
impl Display for GenericBound {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
GenericBound::TraitBound {
trait_,
generic_params,
modifier,
} => {
if !generic_params.is_empty() {
write!(
f,
"for<{}> ",
generic_params
.iter()
.map(|p| p.to_string())
.collect::<Vec<_>>()
.join(", ")
)?;
}
write!(f, "{}", trait_)?;
match modifier {
TraitBoundModifier::None => Ok(()),
TraitBoundModifier::Maybe => write!(f, "?"),
TraitBoundModifier::MaybeConst => write!(f, " + const"),
}
}
GenericBound::Outlives(lifetime) => write!(f, "{}", lifetime),
GenericBound::Use(args) => {
write!(
f,
"use<{}>",
args.iter()
.map(|arg| match arg {
PreciseCapturingArg::Lifetime(name) => name.clone(),
PreciseCapturingArg::Param(name) => name.clone(),
})
.collect::<Vec<_>>()
.join(", ")
)
}
}
}
}
#[derive(
Clone,
Copy,
Debug,
PartialEq,
Eq,
Hash,
Serialize,
Deserialize,
bincode::Decode,
bincode::Encode,
)]
#[serde(rename_all = "snake_case")]
pub enum TraitBoundModifier {
None,
Maybe,
MaybeConst,
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
#[serde(rename_all = "snake_case")]
pub enum PreciseCapturingArg {
Lifetime(String),
Param(String),
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
#[serde(rename_all = "snake_case")]
pub enum Term {
Type(Type),
Constant(Constant),
}
impl Display for Term {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Term::Type(t) => write!(f, "{}", t),
Term::Constant(c) => write!(f, "{}", c),
}
}
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
#[serde(rename_all = "snake_case")]
pub enum Type {
ResolvedPath(Path),
DynTrait(DynTrait),
Generic(String),
Primitive(String),
FunctionPointer(Box<FunctionPointer>),
Tuple(Vec<Type>),
Slice(Box<Type>),
Array {
#[serde(rename = "type")]
type_: Box<Type>,
len: String,
},
Pat {
#[serde(rename = "type")]
type_: Box<Type>,
#[doc(hidden)]
__pat_unstable_do_not_use: String,
},
ImplTrait(Vec<GenericBound>),
Infer,
RawPointer {
is_mutable: bool,
#[serde(rename = "type")]
type_: Box<Type>,
},
BorrowedRef {
lifetime: Option<String>,
is_mutable: bool,
#[serde(rename = "type")]
type_: Box<Type>,
},
QualifiedPath {
name: String,
args: Option<Box<GenericArgs>>,
self_type: Box<Type>,
#[serde(rename = "trait")]
trait_: Option<Path>,
},
}
impl Display for Type {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Type::ResolvedPath(path) => write!(f, "{}", path.path),
Type::DynTrait(_) => write!(f, "dyn <trait>"),
Type::Generic(name) => write!(f, "{}", name),
Type::Primitive(name) => write!(f, "{}", name),
Type::FunctionPointer(_) => write!(f, "fn(...)"),
Type::Tuple(t) => write!(
f,
"({})",
t.iter()
.map(|ty| format!("{}", ty))
.collect::<Vec<_>>()
.join(", ")
),
Type::Slice(s) => write!(f, "[{}]", s),
Type::Array { type_, len } => write!(f, "[{}; {}]", type_, len),
Type::Pat { .. } => write!(f, "<pattern type>"),
Type::ImplTrait(_) => write!(f, "impl <trait bounds>"),
Type::Infer => write!(f, "_"),
Type::RawPointer { is_mutable, .. } => {
if *is_mutable {
write!(f, "*mut ...")
} else {
write!(f, "*const ...")
}
}
Type::BorrowedRef {
is_mutable,
lifetime,
type_,
} => {
if *is_mutable {
write!(
f,
"&mut{} {}",
lifetime.as_ref().unwrap_or(&"".into()),
type_
)
} else {
write!(f, "&{} {}", lifetime.as_ref().unwrap_or(&"_".into()), type_)
}
}
Type::QualifiedPath { name, .. } => write!(f, "<qualified path>::{}", name),
}
}
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
pub struct Path {
pub path: String,
pub id: Id,
pub args: Option<Box<GenericArgs>>,
}
impl Display for Path {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}<{}>",
self.path,
self.args
.as_ref()
.map(|args| args.to_string())
.unwrap_or_default()
)
}
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
pub struct FunctionPointer {
pub sig: FunctionSignature,
pub generic_params: Vec<GenericParamDef>,
pub header: FunctionHeader,
}
pub type Argument = (String, Type);
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
pub struct FunctionSignature {
pub inputs: Vec<Argument>,
pub output: Option<Type>,
pub is_c_variadic: bool,
}
impl Display for FunctionSignature {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "fn(")?;
for (i, (name, ty)) in self.inputs.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{}: {}", name, ty)?;
}
if self.is_c_variadic {
if !self.inputs.is_empty() {
write!(f, ", ")?;
}
write!(f, "...")?;
}
write!(f, ")")?;
if let Some(output) = &self.output {
write!(f, " -> {}", output)?;
}
Ok(())
}
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
pub struct Trait {
pub is_auto: bool,
pub is_unsafe: bool,
pub is_dyn_compatible: bool,
pub items: Vec<Id>,
pub generics: Generics,
pub bounds: Vec<GenericBound>,
pub implementations: Vec<Id>,
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
pub struct TraitAlias {
pub generics: Generics,
pub params: Vec<GenericBound>,
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
pub struct Impl {
pub is_unsafe: bool,
pub generics: Generics,
pub provided_trait_methods: Vec<String>,
#[serde(rename = "trait")]
pub trait_: Option<Path>,
#[serde(rename = "for")]
pub for_: Type,
pub items: Vec<Id>,
pub is_negative: bool,
pub is_synthetic: bool,
pub blanket_impl: Option<Type>,
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
#[serde(rename_all = "snake_case")]
pub struct Use {
pub source: String,
pub name: String,
pub id: Option<Id>,
pub is_glob: bool,
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
pub struct ProcMacro {
pub kind: MacroKind,
pub helpers: Vec<String>,
}
#[derive(
Clone,
Copy,
Debug,
PartialEq,
Eq,
Hash,
Serialize,
Deserialize,
bincode::Decode,
bincode::Encode,
)]
#[serde(rename_all = "snake_case")]
pub enum MacroKind {
Bang,
Attr,
Derive,
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
pub struct TypeAlias {
#[serde(rename = "type")]
pub type_: Type,
pub generics: Generics,
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
pub struct Static {
#[serde(rename = "type")]
pub type_: Type,
pub is_mutable: bool,
pub expr: String,
pub is_unsafe: bool,
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, bincode::Decode, bincode::Encode,
)]
pub struct Primitive {
pub name: String,
pub impls: Vec<Id>,
}