#![warn(missing_docs)]
use std::{fmt::{self, Display}, borrow::Borrow};
mod parser;
pub use parser::{ Parser, ParseError, ParseErrorKind };
mod write;
pub use write::Writer;
mod idcode;
pub use idcode::{IdCode, InvalidIdCode};
mod value;
pub use value::{ Value, Vector, VectorIter, InvalidValue };
mod timescale;
pub use timescale::{ TimescaleUnit, InvalidTimescaleUnit };
mod scope;
pub use scope::{
Scope,
ScopeItem,
ScopeType,
InvalidScopeType,
Var,
VarType,
InvalidVarType,
ReferenceIndex,
InvalidReferenceIndex,
};
macro_rules! unit_error_struct {
($name:ident, $err:literal) => {
#[doc = concat!("Parse error for ", $err, ".")]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub struct $name;
impl Display for $name {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, $err)
}
}
impl std::error::Error for $name {}
};
}
pub(crate) use unit_error_struct;
#[derive(Debug, PartialEq, Clone)]
#[non_exhaustive]
pub enum Command {
Comment(String),
Date(String),
Version(String),
Timescale(u32, TimescaleUnit),
ScopeDef(ScopeType, String),
Upscope,
VarDef(VarType, u32, IdCode, String, Option<ReferenceIndex>),
Enddefinitions,
Timestamp(u64),
ChangeScalar(IdCode, Value),
ChangeVector(IdCode, Vector),
ChangeReal(IdCode, f64),
ChangeString(IdCode, String),
Begin(SimulationCommand),
End(SimulationCommand),
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[non_exhaustive]
#[allow(missing_docs)]
pub enum SimulationCommand {
Dumpall,
Dumpoff,
Dumpon,
Dumpvars,
}
impl Display for SimulationCommand {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use SimulationCommand::*;
write!(
f,
"{}",
match *self {
Dumpall => "dumpall",
Dumpoff => "dumpoff",
Dumpon => "dumpon",
Dumpvars => "dumpvars",
}
)
}
}
#[derive(Debug, Default)]
#[non_exhaustive]
pub struct Header {
pub date: Option<String>,
pub version: Option<String>,
pub timescale: Option<(u32, TimescaleUnit)>,
pub items: Vec<ScopeItem>,
}
fn find_parent_scope<'a>(
mut items: &'a [ScopeItem],
path: &[impl Borrow<str>]
) -> Option<&'a [ScopeItem]> {
for name in path {
items = items.iter().find_map(|item| match item {
ScopeItem::Scope(scope) if scope.identifier == name.borrow() => {
Some(&scope.items[..])
}
_ => None,
})?;
}
Some(items)
}
impl Header {
pub fn find_scope<S>(&self, path: &[S]) -> Option<&Scope>
where
S: std::borrow::Borrow<str>,
{
let (name, parent_path) = path.split_last()?;
let parent = find_parent_scope(&self.items, parent_path)?;
parent.iter().find_map(|item| match item {
ScopeItem::Scope(scope) if scope.identifier == name.borrow() => Some(scope),
_ => None,
})
}
pub fn find_var<S>(&self, path: &[S]) -> Option<&Var>
where
S: std::borrow::Borrow<str>,
{
let (name, parent_path) = path.split_last()?;
let parent = find_parent_scope(&self.items, parent_path)?;
parent.iter().find_map(|item| match item {
ScopeItem::Var(v) if v.reference == name.borrow() => Some(v),
_ => None,
})
}
}