use super::*;
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
pub enum PrimaryKind {
Entity,
Configuration,
Package,
PackageInstance,
Context,
}
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
pub enum SecondaryKind {
Architecture,
PackageBody,
}
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
pub enum AnyKind {
Primary(PrimaryKind),
Secondary(SecondaryKind),
}
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub enum UnitKey {
Primary(Symbol),
Secondary(Symbol, Symbol),
}
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub struct UnitId {
library_name: Symbol,
kind: AnyKind,
key: UnitKey,
}
impl UnitId {
pub fn primary(library_name: &Symbol, kind: PrimaryKind, name: &Symbol) -> UnitId {
UnitId {
library_name: library_name.clone(),
kind: AnyKind::Primary(kind),
key: UnitKey::Primary(name.clone()),
}
}
pub fn secondary(
library_name: &Symbol,
kind: SecondaryKind,
primary_name: &Symbol,
name: &Symbol,
) -> UnitId {
UnitId {
library_name: library_name.clone(),
kind: AnyKind::Secondary(kind),
key: UnitKey::Secondary(primary_name.clone(), name.clone()),
}
}
pub fn package(library_name: &Symbol, name: &Symbol) -> UnitId {
Self::primary(library_name, PrimaryKind::Package, name)
}
pub fn library_name(&self) -> &Symbol {
&self.library_name
}
pub fn primary_name(&self) -> &Symbol {
match self.key {
UnitKey::Primary(ref name) => name,
UnitKey::Secondary(ref name, _) => name,
}
}
}
pub trait HasUnitId {
fn unit_id(&self) -> &UnitId;
fn kind(&self) -> AnyKind {
self.unit_id().kind
}
fn key(&self) -> &UnitKey {
&self.unit_id().key
}
fn secondary_kind(&self) -> Option<SecondaryKind> {
match self.unit_id().kind {
AnyKind::Secondary(kind) => Some(kind),
AnyKind::Primary(..) => None,
}
}
fn describe(&self) -> String {
match self.key() {
UnitKey::Primary(name) => format!("{} '{}'", self.kind().describe(), name),
UnitKey::Secondary(primary_name, name) => match self.secondary_kind().unwrap() {
SecondaryKind::Architecture => format!(
"{} '{}' of '{}'",
self.kind().describe(),
name,
primary_name
),
SecondaryKind::PackageBody => format!("{} '{}'", self.kind().describe(), name),
},
}
}
}
impl HasUnitId for UnitId {
fn unit_id(&self) -> &UnitId {
self
}
}
macro_rules! delegate_primary {
($primary:expr, $unit:ident, $block:expr) => {
match $primary {
AnyPrimaryUnit::Entity($unit) => $block,
AnyPrimaryUnit::Package($unit) => $block,
AnyPrimaryUnit::PackageInstance($unit) => $block,
AnyPrimaryUnit::Context($unit) => $block,
AnyPrimaryUnit::Configuration($unit) => $block,
}
};
}
macro_rules! delegate_secondary {
($primary:expr, $unit:ident, $block:expr) => {
match $primary {
AnySecondaryUnit::Architecture($unit) => $block,
AnySecondaryUnit::PackageBody($unit) => $block,
}
};
}
macro_rules! delegate_any {
($primary:expr, $unit:ident, $block:expr) => {
match $primary {
AnyDesignUnit::Primary($unit) => $block,
AnyDesignUnit::Secondary($unit) => $block,
}
};
}
impl AnyKind {
pub fn kind_of(unit: &AnyDesignUnit) -> AnyKind {
match unit {
AnyDesignUnit::Primary(unit) => AnyKind::Primary(PrimaryKind::kind_of(unit)),
AnyDesignUnit::Secondary(unit) => AnyKind::Secondary(SecondaryKind::kind_of(unit)),
}
}
pub fn describe(&self) -> &str {
match self {
AnyKind::Primary(kind) => kind.describe(),
AnyKind::Secondary(kind) => kind.describe(),
}
}
}
impl PrimaryKind {
pub fn kind_of(unit: &AnyPrimaryUnit) -> PrimaryKind {
match unit {
AnyPrimaryUnit::Entity(..) => PrimaryKind::Entity,
AnyPrimaryUnit::Configuration(..) => PrimaryKind::Configuration,
AnyPrimaryUnit::Package(..) => PrimaryKind::Package,
AnyPrimaryUnit::PackageInstance(..) => PrimaryKind::PackageInstance,
AnyPrimaryUnit::Context(..) => PrimaryKind::Context,
}
}
pub fn describe(&self) -> &str {
match self {
PrimaryKind::Entity => "entity",
PrimaryKind::Configuration => "configuration",
PrimaryKind::Package => "package",
PrimaryKind::PackageInstance => "package instance",
PrimaryKind::Context => "context",
}
}
}
impl SecondaryKind {
pub fn kind_of(unit: &AnySecondaryUnit) -> SecondaryKind {
match unit {
AnySecondaryUnit::Architecture(..) => SecondaryKind::Architecture,
AnySecondaryUnit::PackageBody(..) => SecondaryKind::PackageBody,
}
}
pub fn describe(&self) -> &str {
match self {
SecondaryKind::Architecture => "architecture",
SecondaryKind::PackageBody => "package body",
}
}
}
impl AnyDesignUnit {
pub fn as_primary(&self) -> Option<&AnyPrimaryUnit> {
if let AnyDesignUnit::Primary(ref unit) = self {
Some(unit)
} else {
None
}
}
}
pub fn capitalize(string: &str) -> String {
let mut result = String::with_capacity(string.len());
let mut chars = string.chars();
if let Some(chr) = chars.next() {
result.push(chr.to_ascii_uppercase());
}
for chr in chars {
result.push(chr);
}
result
}