use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign};
use cargo_metadata::DependencyKind as MetaDepKind;
#[derive(Clone, Copy, Debug, Default)]
pub(crate) struct DepInfo {
pub kind: DepKind,
pub is_target_dep: bool,
pub is_optional: bool,
pub is_optional_direct: bool,
pub visited: bool,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) struct DepKind {
pub host: BuildFlag,
pub target: BuildFlag,
}
impl DepKind {
pub const NORMAL: Self = Self { host: BuildFlag::Never, target: BuildFlag::Always };
pub const BUILD: Self = Self { host: BuildFlag::Always, target: BuildFlag::Never };
pub const DEV: Self = Self { host: BuildFlag::Never, target: BuildFlag::Test };
pub const BUILD_OF_DEV: Self = Self { host: BuildFlag::Test, target: BuildFlag::Never };
pub const NORMAL_AND_BUILD: Self = Self { host: BuildFlag::Always, target: BuildFlag::Always };
pub const DEV_AND_BUILD: Self = Self { host: BuildFlag::Always, target: BuildFlag::Test };
pub const NORMAL_AND_BUILD_OF_DEV: Self =
Self { host: BuildFlag::Test, target: BuildFlag::Always };
pub const DEV_AND_BUILD_OF_DEV: Self = Self { host: BuildFlag::Test, target: BuildFlag::Test };
pub const UNKNOWN: Self = Self { host: BuildFlag::Never, target: BuildFlag::Never };
pub fn new(kind: MetaDepKind, proc_macro: bool) -> Self {
let res = Self::from(kind);
if proc_macro {
Self { host: res.target, target: BuildFlag::Never }
} else {
res
}
}
pub fn combine_incoming(&mut self, other: Self) {
if *self == Self::UNKNOWN || other == Self::UNKNOWN {
*self = Self::UNKNOWN;
} else {
self.host |= other.host;
self.target |= other.target;
}
}
pub fn update_outgoing(&mut self, node_kind: Self) {
if node_kind == Self::UNKNOWN || *self == Self::UNKNOWN {
} else {
self.host = (self.target & node_kind.host)
| (self.host & node_kind.target)
| (self.host & node_kind.host);
self.target &= node_kind.target;
}
}
pub fn is_dev_only(&self) -> bool {
self.host != BuildFlag::Always && self.target != BuildFlag::Always
}
}
impl Default for DepKind {
fn default() -> Self {
Self::from(MetaDepKind::Normal)
}
}
impl From<MetaDepKind> for DepKind {
fn from(kind: MetaDepKind) -> Self {
match kind {
MetaDepKind::Normal => Self::NORMAL,
MetaDepKind::Build => Self::BUILD,
MetaDepKind::Development => Self::DEV,
MetaDepKind::Unknown => Self::UNKNOWN,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum BuildFlag {
Always,
Test,
Never,
}
impl BitAnd for BuildFlag {
type Output = Self;
fn bitand(self, rhs: Self) -> Self {
use BuildFlag::*;
match (self, rhs) {
(Always, Always) => Always,
(Always, Test) | (Test, Always) | (Test, Test) => Test,
_ => Never,
}
}
}
impl BitAndAssign for BuildFlag {
fn bitand_assign(&mut self, rhs: Self) {
*self = *self & rhs;
}
}
impl BitOr for BuildFlag {
type Output = Self;
fn bitor(self, rhs: Self) -> Self {
use BuildFlag::*;
match (self, rhs) {
(Never, Never) => Never,
(Never, Test) | (Test, Never) | (Test, Test) => Test,
_ => Always,
}
}
}
impl BitOrAssign for BuildFlag {
fn bitor_assign(&mut self, rhs: Self) {
*self = *self | rhs;
}
}