use crate::stream_parser::{LefDefLexer, LefDefParseError};
use itertools::PeekingNext;
use libreda_stream_parser::{tokenize, Tokenized};
use std::fmt;
use std::str::FromStr;
#[derive(Clone, Debug)]
pub enum PropertyType {
Integer,
Real,
String,
}
impl FromStr for PropertyType {
type Err = ();
fn from_str(input: &str) -> Result<Self, Self::Err> {
match input {
"INTEGER" => Ok(Self::Integer),
"REAL" => Ok(Self::Real),
"STRING" => Ok(Self::String),
_ => Err(()),
}
}
}
impl fmt::Display for PropertyType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Integer => f.write_str("INTEGER"),
Self::Real => f.write_str("REAL"),
Self::String => f.write_str("STRING"),
}
}
}
#[derive(Clone, Debug)]
pub enum PropertyValue {
Int(i32),
Real(f64),
String(String),
}
impl fmt::Display for PropertyValue {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
PropertyValue::Int(v) => write!(f, "{}", v),
PropertyValue::Real(v) => write!(f, "{}", v),
PropertyValue::String(v) => write!(f, r#""{}""#, v),
}
}
}
pub fn read_point<T: FromStr, I>(
tokens: &mut Tokenized<I, LefDefLexer>,
) -> Result<(T, T), LefDefParseError>
where
I: Iterator<Item = char> + PeekingNext,
{
let uses_parentheses = tokens.test_str("(")?;
let x: T = tokens.take_and_parse()?;
tokens.test_str(",")?;
let y: T = tokens.take_and_parse()?;
if uses_parentheses {
tokens.expect_str(")")?;
}
Ok((x, y))
}
pub fn read_polygon<T: FromStr, I>(
tokens: &mut Tokenized<I, LefDefLexer>,
) -> Result<Vec<(T, T)>, LefDefParseError>
where
I: Iterator<Item = char> + PeekingNext,
{
let mut points = Vec::new();
loop {
if tokens.test_str(";")? {
break;
} else {
points.push(read_point(tokens)?);
}
}
Ok(points)
}
pub fn read_rect<T: FromStr, I>(
tokens: &mut Tokenized<I, LefDefLexer>,
) -> Result<((T, T), (T, T)), LefDefParseError>
where
I: Iterator<Item = char> + PeekingNext,
{
let p1 = read_point(tokens)?;
let p2 = read_point(tokens)?;
Ok((p1, p2))
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
pub struct Symmetry {
x: bool,
y: bool,
r90: bool,
}
impl Symmetry {
pub fn new(x: bool, y: bool, r90: bool) -> Self {
Self { x, y, r90 }
}
pub fn x() -> Self {
Self::new(true, false, false)
}
pub fn y() -> Self {
Self::new(false, true, false)
}
pub fn r90() -> Self {
Self::new(false, false, true)
}
pub fn union(self, other: Self) -> Self {
Self {
x: self.x | other.x,
y: self.y | other.y,
r90: self.r90 | other.r90,
}
}
}
impl FromStr for Symmetry {
type Err = ();
fn from_str(input: &str) -> Result<Self, Self::Err> {
match input {
"X" => Ok(Self::x()),
"Y" => Ok(Self::y()),
"R90" => Ok(Self::r90()),
_ => Err(()),
}
}
}
impl fmt::Display for Symmetry {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.x {
f.write_str("X")?;
}
if self.y {
f.write_str("Y")?;
}
if self.r90 {
f.write_str("R90")?;
}
Ok(())
}
}
#[derive(Clone, Debug, Default)]
pub struct AntennaRules {
model: (),
area_ratio: (),
diff_area_ration: (),
cum_area_ratio: (),
cum_diff_area_ratio: (),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum Orient {
N,
S,
E,
W,
FN,
FS,
FE,
FW,
}
impl Default for Orient {
fn default() -> Self {
Self::N
}
}
impl Orient {
pub fn decomposed(&self) -> (Self, bool) {
match self {
Orient::FN => (Orient::N, true),
Orient::FS => (Orient::S, true),
Orient::FE => (Orient::E, true),
Orient::FW => (Orient::W, true),
other => (*other, false),
}
}
pub fn flipped(&self) -> Self {
use Orient::*;
match self {
N => FN,
S => FS,
E => FE,
W => FW,
FN => N,
FS => S,
FE => E,
FW => W,
}
}
}
impl FromStr for Orient {
type Err = ();
fn from_str(input: &str) -> Result<Self, Self::Err> {
match input {
"N" => Ok(Self::N),
"S" => Ok(Self::S),
"E" => Ok(Self::E),
"W" => Ok(Self::W),
"FN" => Ok(Self::FN),
"FS" => Ok(Self::FS),
"FE" => Ok(Self::FE),
"FW" => Ok(Self::FW),
_ => Err(()),
}
}
}
impl fmt::Display for Orient {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::N => f.write_str("N"),
Self::S => f.write_str("S"),
Self::E => f.write_str("E"),
Self::W => f.write_str("W"),
Self::FN => f.write_str("FN"),
Self::FS => f.write_str("FS"),
Self::FE => f.write_str("FE"),
Self::FW => f.write_str("FW"),
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum PinDirection {
Input,
Output(bool),
Inout,
Feedthru,
}
impl FromStr for PinDirection {
type Err = ();
fn from_str(input: &str) -> Result<Self, Self::Err> {
match input {
"INPUT" => Ok(Self::Input),
"OUTPUT" => Ok(Self::Output(false)),
"INOUT" => Ok(Self::Inout),
"FEEDTHRU" => Ok(Self::Feedthru),
_ => Err(()),
}
}
}
impl fmt::Display for PinDirection {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Input => f.write_str("INPUT"),
Self::Output(false) => f.write_str("OUTPUT"),
Self::Output(true) => f.write_str("OUTPUT TRISTATE"),
Self::Inout => f.write_str("INOUT"),
Self::Feedthru => f.write_str("FEEDTHRU"),
}
}
}