use std::fmt;
use std::hash::Hash;
use std::sync::Arc;
use arcstr::Substr;
#[derive(PartialEq, Eq, Clone)]
pub struct HierName {
pub cur: Substr,
pub prev: Option<Arc<HierName>>,
}
pub struct HierNameRevIter<'i>(Option<&'i HierName>);
impl<'i> Iterator for HierNameRevIter<'i> {
type Item = &'i Substr;
#[inline]
fn next(&mut self) -> Option<&'i Substr> {
let name = self.0?;
if name.cur.len() == 0 {
return None
}
let ret = &name.cur;
self.0 = name.prev.as_ref().map(|a| a.as_ref());
Some(ret)
}
}
impl<'i> IntoIterator for &'i HierName {
type Item = &'i Substr;
type IntoIter = HierNameRevIter<'i>;
#[inline]
fn into_iter(self) -> HierNameRevIter<'i> {
HierNameRevIter(Some(self))
}
}
impl Hash for HierName {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
for s in self.iter() {
s.hash(state);
}
}
}
impl HierName {
#[inline]
pub fn single(cur: Substr) -> Self {
HierName { cur, prev: None }
}
#[inline]
pub fn empty() -> Self {
HierName { cur: arcstr::literal_substr!(""), prev: None }
}
#[inline]
pub fn is_empty(&self) -> bool {
self.prev.is_none() && self.cur.len() == 0
}
#[inline]
pub fn iter(&self) -> HierNameRevIter {
(&self).into_iter()
}
}
impl fmt::Display for HierName {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(v) = &self.prev {
write!(f, "{}/", v)?;
}
write!(f, "{}", self.cur)
}
}
impl fmt::Debug for HierName {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "HierName({})", self)
}
}
#[test]
fn test_hier_name() {
use arcstr::literal_substr;
let h1 = Arc::from(HierName{
cur: literal_substr!("top"),
prev: None
});
let h2 = Arc::from(HierName{
cur: literal_substr!("mod1"),
prev: Some(h1.clone())
});
let h3 = Arc::from(HierName{
cur: literal_substr!("leaf1"),
prev: Some(h2.clone())
});
let h3_ = Arc::from(HierName{
cur: literal_substr!("leaf2"),
prev: Some(h2.clone())
});
assert_eq!(format!("{}", h3), "top/mod1/leaf1");
assert_eq!(format!("{:?}", h3_), "HierName(top/mod1/leaf2)");
assert_eq!(h3.iter().map(|a| a.as_ref()).collect::<Vec<&str>>(),
vec!["leaf1", "mod1", "top"]);
}
pub trait GeneralHierName {
fn ident_vec(&self) -> Vec<&str>;
}
impl<T, S> GeneralHierName for T
where for<'i> &'i T: IntoIterator<Item = &'i S>,
T: Hash,
S: AsRef<str>
{
#[inline]
fn ident_vec(&self) -> Vec<&str> {
self.into_iter().map(|a| a.as_ref()).collect()
}
}
impl Hash for dyn GeneralHierName + '_ {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
for s in self.ident_vec().iter().rev() {
s.hash(state);
}
}
}
impl<'i> std::borrow::Borrow<dyn GeneralHierName + 'i> for HierName {
#[inline]
fn borrow(&self) -> &(dyn GeneralHierName + 'i) {
self
}
}
impl<'i> std::borrow::Borrow<dyn GeneralHierName + 'i> for &'i HierName {
#[inline]
fn borrow(&self) -> &(dyn GeneralHierName + 'i) {
*self
}
}
impl PartialEq for dyn GeneralHierName + '_ {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.ident_vec() == other.ident_vec()
}
}
impl Eq for dyn GeneralHierName + '_ {}
pub trait GeneralPinName {
fn hierarchy(&self) -> &dyn GeneralHierName;
fn pin_type(&self) -> &str;
fn bus_id(&self) -> Option<isize>;
}
impl<C, S> GeneralPinName for (C, S, Option<isize>)
where C: GeneralHierName, S: AsRef<str>
{
#[inline]
fn hierarchy(&self) -> &dyn GeneralHierName {
&self.0
}
#[inline]
fn pin_type(&self) -> &str {
self.1.as_ref()
}
#[inline]
fn bus_id(&self) -> Option<isize> {
self.2
}
}
impl Hash for dyn GeneralPinName + '_ {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
for s in self.hierarchy().ident_vec().iter().rev() {
s.hash(state);
}
self.pin_type().hash(state);
self.bus_id().hash(state);
}
}
impl<'i> std::borrow::Borrow<dyn GeneralPinName + 'i>
for (HierName, Substr, Option<isize>)
{
#[inline]
fn borrow(&self) -> &(dyn GeneralPinName + 'i) {
self
}
}
impl<'i, 'j> std::borrow::Borrow<dyn GeneralPinName + 'i>
for &'j (HierName, Substr, Option<isize>)
{
#[inline]
fn borrow(&self) -> &(dyn GeneralPinName + 'i) {
*self
}
}
impl PartialEq for dyn GeneralPinName + '_ {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.bus_id() == other.bus_id() &&
self.pin_type() == other.pin_type() &&
self.hierarchy().ident_vec() == other.hierarchy().ident_vec()
}
}
impl Eq for dyn GeneralPinName + '_ {}
pub struct RefPinName<'a, 'b, T: GeneralHierName>(
pub &'a T, pub &'b str, pub Option<isize>
);
impl<'a, 'b, T: GeneralHierName + Hash> Hash for RefPinName<'a, 'b, T> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.0.hash(state);
self.1.hash(state);
self.2.hash(state);
}
}
impl<'a, 'b, T: GeneralHierName> GeneralPinName for RefPinName<'a, 'b, T> {
#[inline]
fn hierarchy(&self) -> &dyn GeneralHierName {
&*self.0
}
#[inline]
fn pin_type(&self) -> &str {
self.1.as_ref()
}
#[inline]
fn bus_id(&self) -> Option<isize> {
self.2
}
}