use serde::{Deserialize, Serialize};
use crate::category::{Category, Termination};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Loc {
pub file: String,
pub line: u32,
pub col: u32,
}
impl std::fmt::Display for Loc {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}:{}:{}", self.file, self.line, self.col)
}
}
#[derive(
Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize,
)]
pub struct FuncKey(pub String);
impl std::fmt::Display for FuncKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.0)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum EdgeKind {
Static,
Drop,
Vtable,
FnPtr,
Unresolved,
}
impl EdgeKind {
#[must_use]
pub const fn is_exact(self) -> bool {
matches!(self, Self::Static | Self::Drop)
}
#[must_use]
pub const fn name(self) -> &'static str {
match self {
Self::Static => "static",
Self::Drop => "drop",
Self::Vtable => "vtable",
Self::FnPtr => "fn-ptr",
Self::Unresolved => "unresolved",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum UnwindOrigin {
Site(u32),
Call(u32),
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct Guard {
pub normal: bool,
pub origins: Vec<UnwindOrigin>,
}
impl Guard {
#[must_use]
pub const fn always() -> Self {
Self {
normal: true,
origins: Vec::new(),
}
}
#[must_use]
pub const fn is_dead(&self) -> bool {
!self.normal && self.origins.is_empty()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PanicSite {
pub category: Category,
pub termination: Termination,
pub reason: String,
pub sink: Option<String>,
pub loc: Option<Loc>,
pub guard: Guard,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CallSite {
pub callee: Option<FuncKey>,
pub callee_display: String,
pub kind: EdgeKind,
pub loc: Option<Loc>,
pub guard: Guard,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Body {
pub key: FuncKey,
pub display: String,
pub krate: String,
pub loc: Option<Loc>,
pub sites: Vec<PanicSite>,
pub calls: Vec<CallSite>,
pub opaque: bool,
pub local: bool,
}
impl Body {
#[must_use]
pub const fn opaque(key: FuncKey, display: String, krate: String) -> Self {
Self {
key,
display,
krate,
loc: None,
sites: Vec::new(),
calls: Vec::new(),
opaque: true,
local: false,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum StdMode {
Shipped,
Full,
}
impl StdMode {
#[must_use]
pub const fn name(self) -> &'static str {
match self {
Self::Shipped => "shipped",
Self::Full => "full",
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BuildConfig {
pub rustc: String,
pub profile: String,
pub debug_assertions: bool,
pub overflow_checks: bool,
pub std_mode: StdMode,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Artifact {
pub krate: String,
pub config: BuildConfig,
pub bodies: Vec<Body>,
}