use serde::{Deserialize, Serialize};
use std::{fmt::Debug, hash::Hash};
#[derive(Clone, Serialize, Deserialize)]
pub struct IPath {
pub leading_colon: Option<ISpan>,
pub segments: Vec<IPathSegment>,
}
#[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
pub struct IPathSegment {
pub ident: IIdent,
}
impl IPath {
pub fn starts_with_absolute(&self, segments: &[&str]) -> bool {
if self.leading_colon.is_none() {
return false;
}
if self.segments.len() < segments.len() {
return false;
}
for (self_segment, other_segment) in self.segments.iter().zip(segments.iter()) {
if self_segment.ident.name != *other_segment {
return false;
}
}
true
}
pub fn matches_relative(&self, segments: &[&str]) -> bool {
if self.leading_colon.is_some() {
return false;
}
if self.segments.len() != segments.len() {
return false;
}
for (self_segment, other_segment) in self.segments.iter().zip(segments.iter()) {
if self_segment.ident.name != *other_segment {
return false;
}
}
true
}
pub fn from_ident(ident: IIdent) -> Self {
IPath {
leading_colon: None,
segments: vec![IPathSegment { ident }],
}
}
pub fn span(&self) -> &ISpan {
if let Some(last_segment) = self.segments.last() {
&last_segment.ident.span
} else {
&ISpan::Unspecified
}
}
pub fn segments_strs(&self) -> impl Iterator<Item = &str> {
self.segments
.iter()
.map(|segment| segment.ident.name.as_str())
}
pub fn get_ident(&self) -> Option<&IIdent> {
if self.leading_colon.is_none() && self.segments.len() == 1 {
Some(&self.segments[0].ident)
} else {
None
}
}
}
impl PartialEq for IPath {
fn eq(&self, other: &Self) -> bool {
self.leading_colon.is_some() == other.leading_colon.is_some()
&& self.segments == other.segments
}
}
impl Eq for IPath {}
impl Hash for IPath {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
let has_leading_colon = self.leading_colon.is_some();
has_leading_colon.hash(state);
self.segments.hash(state);
}
}
impl Debug for IPath {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.leading_colon.is_some() {
f.write_str("::")?;
}
let mut first = true;
for segment in &self.segments {
if first {
first = false;
} else {
f.write_str("::")?;
}
f.write_str(&segment.ident.name)?;
}
Ok(())
}
}
#[derive(Clone, Serialize, Deserialize)]
pub struct IIdent {
name: String,
span: ISpan,
}
impl IIdent {
pub fn new(name: String, span: ISpan) -> Self {
Self { name, span }
}
pub fn name(&self) -> &str {
&self.name
}
pub fn set_name(&mut self, name: String) {
self.name = name;
}
pub fn into_path(self) -> IPath {
IPath::from_ident(self)
}
pub fn mck_prefixed(&self, prefix: &str) -> IIdent {
let orig_ident_str = self.name();
let stripped_ident_str = orig_ident_str
.strip_prefix("__mck_")
.unwrap_or(orig_ident_str);
IIdent::new(
format!("__mck_{}_{}", prefix, stripped_ident_str),
self.span.clone(),
)
}
}
impl PartialEq for IIdent {
fn eq(&self, other: &Self) -> bool {
self.name == other.name
}
}
impl Eq for IIdent {}
impl Hash for IIdent {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.name.hash(state);
}
}
impl PartialOrd for IIdent {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for IIdent {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.name.cmp(&other.name)
}
}
impl Debug for IIdent {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.name)
}
}
#[derive(Clone, Serialize, Deserialize)]
pub enum ISpan {
Unspecified, }