use std::collections::hash_map::DefaultHasher;
use std::fmt;
use std::hash::{Hash, Hasher};
use crate::matching::{get_or_key, MPMatching};
use crate::segment::MPSegment;
#[derive(Debug, Clone)]
pub struct TSegment {
pub name: u64,
pub text: u64,
}
impl fmt::Display for TSegment {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}: {}", self.name, self.text)
}
}
impl PartialEq for TSegment {
fn eq(&self, other: &Self) -> bool {
self.name == other.name && self.text == other.text
}
}
impl Eq for TSegment {}
impl Hash for TSegment {
fn hash<H: Hasher>(&self, state: &mut H) {
self.name.hash(state);
self.text.hash(state);
}
}
#[derive(Debug, Clone)]
pub struct MPPath<'a> {
pub value: &'a MPSegment,
pub segments: Vec<TSegment>,
pub identity: u64,
}
impl<'a> MPPath<'a> {
pub fn new(segments: Vec<TSegment>, value: &'a MPSegment) -> MPPath {
let mut hasher = DefaultHasher::new();
for segment in segments.iter() {
segment.name.hash(&mut hasher);
}
value.name.hash(&mut hasher);
value.text.hash(&mut hasher);
let identity = hasher.finish();
MPPath {
value,
segments,
identity,
}
}
pub fn len(&self) -> usize {
self.segments.len()
}
pub fn starts_with(&self, path: &MPPath) -> bool {
let lpath = path.len();
self.len() >= lpath && &self.segments[0..lpath] == &path.segments[0..lpath]
}
pub fn paths_after(&'a self, paths: &'a [MPPath]) -> usize {
let mut seen = false;
let mut path_starts_with_self: bool;
let mut i = 0;
for path in paths {
if path.value.is_empty {
i += 1;
continue;
}
path_starts_with_self = path.starts_with(&self);
if path_starts_with_self {
seen = true;
} else if seen {
break;
}
i += 1;
}
i as usize
}
pub fn substitute(&'a self, matching: &'a MPMatching) -> MPPath {
let new_segments = self.segments.clone();
let new_value = get_or_key(&matching, &self.value);
MPPath::new(new_segments, new_value)
}
}
impl<'a> fmt::Display for MPPath<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<{}>", self.value)
}
}
impl<'a> PartialEq for MPPath<'_> {
fn eq(&self, other: &Self) -> bool {
self.identity == other.identity
}
}
impl<'a> Eq for MPPath<'_> {}
impl<'a> Hash for MPPath<'_> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.identity.hash(state);
}
}