diff --git a/crates/fayalite-proc-macros-impl/src/hdl_type_common.rs b/crates/fayalite-proc-macros-impl/src/hdl_type_common.rs index f5b353e..3a0e5e9 100644 --- a/crates/fayalite-proc-macros-impl/src/hdl_type_common.rs +++ b/crates/fayalite-proc-macros-impl/src/hdl_type_common.rs @@ -4612,3 +4612,124 @@ impl MakeHdlTypeExpr for ParsedTypeTuple { }) } } + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub(crate) enum ParsedSimpleVisibility { + Public(Token![pub]), + PubCrate { + pub_token: Token![pub], + paren_token: Paren, + crate_token: Token![crate], + }, + Inherited, +} + +impl From for Visibility { + fn from(value: ParsedSimpleVisibility) -> Self { + match value { + ParsedSimpleVisibility::Public(v) => Visibility::Public(v), + ParsedSimpleVisibility::PubCrate { + pub_token, + paren_token, + crate_token, + } => Visibility::Restricted(syn::VisRestricted { + pub_token, + paren_token, + in_token: None, + path: Box::new(Ident::new("crate", crate_token.span).into()), + }), + ParsedSimpleVisibility::Inherited => Visibility::Inherited, + } + } +} + +impl PartialOrd for ParsedSimpleVisibility { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for ParsedSimpleVisibility { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.visibility_level().cmp(&other.visibility_level()) + } +} + +impl ParsedSimpleVisibility { + const VISIBILITY_LEVEL_INHERITED: u8 = 0; + const VISIBILITY_LEVEL_RESTRICTED: u8 = 1 + Self::VISIBILITY_LEVEL_INHERITED; + const VISIBILITY_LEVEL_PUB_CRATE: u8 = 1 + Self::VISIBILITY_LEVEL_RESTRICTED; + const VISIBILITY_LEVEL_PUB: u8 = 1 + Self::VISIBILITY_LEVEL_PUB_CRATE; + fn visibility_level(self) -> u8 { + match self { + Self::Public(_) => Self::VISIBILITY_LEVEL_PUB, + Self::PubCrate { .. } => Self::VISIBILITY_LEVEL_PUB_CRATE, + Self::Inherited => Self::VISIBILITY_LEVEL_INHERITED, + } + } + pub(crate) fn parse(vis: Visibility) -> Result { + match vis { + Visibility::Public(v) => Ok(Self::Public(v)), + Visibility::Restricted(syn::VisRestricted { + pub_token, + paren_token, + in_token: None, + path, + }) if path.is_ident("crate") => Ok(Self::PubCrate { + pub_token, + paren_token, + crate_token: Token![crate](path.get_ident().expect("just checked").span()), + }), + Visibility::Restricted(v) => Err(v), + Visibility::Inherited => Ok(Self::Inherited), + } + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub(crate) enum ParsedVisibility { + Simple(ParsedSimpleVisibility), + Restricted(syn::VisRestricted), +} + +impl From for Visibility { + fn from(value: ParsedVisibility) -> Self { + match value { + ParsedVisibility::Simple(v) => v.into(), + ParsedVisibility::Restricted(v) => Visibility::Restricted(v), + } + } +} + +impl PartialOrd for ParsedVisibility { + fn partial_cmp(&self, other: &Self) -> Option { + match (self, other) { + (ParsedVisibility::Simple(l), ParsedVisibility::Simple(r)) => Some(l.cmp(r)), + (ParsedVisibility::Simple(l), ParsedVisibility::Restricted(_)) => Some( + l.visibility_level() + .cmp(&ParsedSimpleVisibility::VISIBILITY_LEVEL_RESTRICTED), + ), + (ParsedVisibility::Restricted(_), ParsedVisibility::Simple(r)) => { + Some(ParsedSimpleVisibility::VISIBILITY_LEVEL_RESTRICTED.cmp(&r.visibility_level())) + } + (ParsedVisibility::Restricted(l), ParsedVisibility::Restricted(r)) => { + (l == r).then_some(std::cmp::Ordering::Equal) + } + } + } +} + +impl ParsedVisibility { + #[allow(dead_code)] + pub(crate) fn parse(vis: Visibility) -> Self { + match ParsedSimpleVisibility::parse(vis) { + Ok(simple) => Self::Simple(simple), + Err(restricted) => Self::Restricted(restricted), + } + } + #[allow(dead_code)] + pub(crate) fn min<'a>(&'a self, other: &'a Self) -> Option<&'a Self> { + self.partial_cmp(other) + .map(|ord| if ord.is_lt() { self } else { other }) + } +}