use rustre_parser::ast::{AstToken, IdNode, IdRefNode, Ident};
use std::borrow::Cow;
use std::convert::Infallible;
use std::fmt::{Debug, Display, Formatter};
use std::str::FromStr;
#[derive(Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Id(str);
impl Id {
pub const LUSTRE_PACKAGE: &'static Self = Id::from_str("Lustre");
pub const fn from_str(str: &str) -> &Self {
unsafe { std::mem::transmute(str) }
}
}
impl<'a> Default for &'a Id {
fn default() -> Self {
Id::from_str("")
}
}
impl Default for Box<Id> {
fn default() -> Self {
<&Id>::default().to_owned()
}
}
impl Clone for Box<Id> {
fn clone(&self) -> Self {
self.as_ref().to_owned()
}
}
impl<'a> From<&'a str> for &'a Id {
fn from(value: &'a str) -> Self {
Id::from_str(value)
}
}
impl From<Box<str>> for Box<Id> {
fn from(value: Box<str>) -> Self {
unsafe { std::mem::transmute(value) }
}
}
impl From<String> for Box<Id> {
fn from(value: String) -> Self {
Self::from(value.into_boxed_str())
}
}
impl<'a> From<&'a Id> for Cow<'a, Id> {
fn from(value: &'a Id) -> Self {
Self::Borrowed(value)
}
}
impl<'a> From<Box<Id>> for Cow<'a, Id> {
fn from(value: Box<Id>) -> Self {
Self::Owned(value)
}
}
impl ToOwned for Id {
type Owned = Box<Id>;
fn to_owned(&self) -> Self::Owned {
let box_str = String::from(&self.0).into_boxed_str();
Box::<Id>::from(box_str)
}
}
impl Display for Id {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", &self.0)
}
}
impl Debug for Id {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "`{}`", &self.0)
}
}
#[derive(Clone, Hash, PartialEq)]
pub struct IdRef<'p, 'm> {
package: Option<Cow<'p, Id>>,
member: Cow<'m, Id>,
}
impl<'p, 'm> IdRef<'p, 'm> {
pub fn new(package: Option<impl Into<Cow<'p, Id>>>, member: impl Into<Cow<'m, Id>>) -> Self {
Self {
package: package.map(|p| p.into()),
member: member.into(),
}
}
pub fn new_implicit(member: impl Into<Cow<'m, Id>>) -> Self {
Self {
package: None,
member: member.into(),
}
}
pub fn new_lustre(member: impl Into<Cow<'m, Id>>) -> Self {
Self {
package: Some(Id::LUSTRE_PACKAGE.into()),
member: member.into(),
}
}
pub fn as_package(&self) -> Option<&Id> {
self.package.as_deref()
}
pub fn as_member(&self) -> &Id {
self.member.as_ref()
}
pub fn as_member_implicit(&self) -> Option<&Id> {
Some(self.member.as_ref()).filter(|_| self.package.is_none())
}
pub fn member_eq(&self, other: &Id) -> bool {
self.member.as_ref() == other
}
pub fn into_inner(self) -> (Option<Cow<'p, Id>>, Cow<'m, Id>) {
(self.package, self.member)
}
}
impl<'p, 'm> From<&'m Id> for IdRef<'p, 'm> {
fn from(value: &'m Id) -> Self {
Self::new_implicit(value)
}
}
impl<'p, 'm> Display for IdRef<'p, 'm> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self.package.as_deref() {
Some(package) => write!(f, "{}::{}", &package.0, &self.member.0),
None => write!(f, "{}", &self.member),
}
}
}
impl<'p, 'm> Debug for IdRef<'p, 'm> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self.package.as_deref() {
Some(package) => write!(f, "`{}::{}`", &package.0, &self.member.0),
None => write!(f, "{:?}", &self.member),
}
}
}
impl<'p, 'm> FromStr for IdRef<'p, 'm> {
type Err = Infallible;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s.rsplit_once("::") {
Some((package, model)) => Self::new(
Some(Id::from_str(package).to_owned()),
Id::from_str(model).to_owned(),
),
None => Self::new_implicit(Id::from_str(s).to_owned()),
})
}
}
impl<'a> From<&'a Ident> for &'a Id {
fn from(value: &'a Ident) -> Self {
Id::from_str(value.text())
}
}
impl<'a> From<&'a Ident> for Box<Id> {
fn from(value: &'a Ident) -> Self {
Id::from_str(value.text()).to_owned()
}
}
impl From<Ident> for Box<Id> {
fn from(value: Ident) -> Self {
(&value).into()
}
}
impl<'a> From<&'a IdNode> for Box<Id> {
fn from(value: &'a IdNode) -> Self {
let ident = value.ident().expect("unparseable");
ident.into()
}
}
impl From<IdNode> for Box<Id> {
fn from(value: IdNode) -> Self {
(&value).into()
}
}
impl<'p, 'm> From<&IdRefNode> for IdRef<'p, 'm> {
fn from(value: &IdRefNode) -> Self {
let package = value.package().map(<Box<Id>>::from);
let member = <Box<Id>>::from(value.member());
Self::new(package, member)
}
}
impl<'p, 'm> From<IdRefNode> for IdRef<'p, 'm> {
fn from(value: IdRefNode) -> Self {
(&value).into()
}
}