use scopegraphs_prust_lib::hashmap::HashSet as TrieSet;
use std::collections::HashSet;
use std::fmt::{Debug, Formatter};
use std::hash::Hash;
use std::marker::PhantomData;
use std::rc::Rc;
mod params;
use crate::{Label, Scope, ScopeGraph};
pub use params::*;
use scopegraphs_regular_expressions::RegexMatcher;
pub mod lookup;
#[allow(missing_docs)]
#[derive(Hash, PartialEq, Eq)]
pub enum EdgeOrData<LABEL> {
Data,
Edge(LABEL),
}
impl<LABEL: Debug> Debug for EdgeOrData<LABEL> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
EdgeOrData::Data => write!(f, "$"),
EdgeOrData::Edge(lbl) => write!(f, "@{:?}", lbl),
}
}
}
impl<LABEL: Copy> Clone for EdgeOrData<LABEL> {
fn clone(&self) -> Self {
*self
}
}
impl<LABEL: Copy> Copy for EdgeOrData<LABEL> {}
#[derive(Hash, PartialEq, Eq, Debug)]
enum InnerPath<LABEL> {
Start {
source: Scope,
},
Step {
prefix: Path<LABEL>,
label: LABEL,
target: Scope,
},
}
#[derive(Clone)]
pub struct Path<LABEL> {
inner_path: Rc<InnerPath<LABEL>>,
scopes: Rc<TrieSet<Scope>>,
}
impl<LABEL> PartialEq for Path<LABEL>
where
Scope: PartialEq,
LABEL: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.inner_path == other.inner_path
}
}
impl<LABEL> Eq for Path<LABEL>
where
Scope: Eq,
LABEL: Eq,
{
}
impl<LABEL> Hash for Path<LABEL>
where
Scope: Hash,
LABEL: Hash,
{
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.inner_path.hash(state);
}
}
impl<LABEL> Debug for Path<LABEL>
where
LABEL: Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Path")
.field("inner_path", &self.inner_path)
.finish()
}
}
#[derive(Hash, PartialEq, Eq, Debug)]
pub struct ResolvedPath<'sg, LABEL, DATA> {
path: Path<LABEL>,
pub(crate) data: &'sg DATA,
}
impl<LABEL: Clone, DATA> Clone for ResolvedPath<'_, LABEL, DATA> {
fn clone(&self) -> Self {
Self {
path: self.path.clone(),
data: self.data,
}
}
}
impl<LABEL, DATA> ResolvedPath<'_, LABEL, DATA> {
pub fn path(&self) -> &Path<LABEL> {
&self.path
}
pub fn data(&self) -> &DATA {
self.data
}
}
impl<LABEL> Path<LABEL> {
pub fn new(source: Scope) -> Self {
Self {
inner_path: Rc::new(InnerPath::Start { source }),
scopes: Rc::new(TrieSet::new().insert(source)),
}
}
pub fn target(&self) -> Scope {
match self.inner_path.as_ref() {
InnerPath::Start { source } => *source,
InnerPath::Step { target, .. } => *target,
}
}
pub fn step(&self, label: LABEL, target: Scope) -> Option<Self> {
if self.scopes.search(&target) {
None
} else {
Some(Self {
inner_path: Rc::new(InnerPath::Step {
prefix: Self {
inner_path: self.inner_path.clone(),
scopes: self.scopes.clone(),
},
label,
target,
}),
scopes: Rc::new(self.scopes.insert(target)),
})
}
}
pub fn resolve<DATA>(self, data: &DATA) -> ResolvedPath<'_, LABEL, DATA> {
ResolvedPath { path: self, data }
}
}
#[derive(Debug)]
pub struct Env<'sg, LABEL: 'sg, DATA>(HashSet<ResolvedPath<'sg, LABEL, DATA>>);
impl<'a, 'sg, LABEL, DATA> IntoIterator for &'a Env<'sg, LABEL, DATA> {
type Item = &'a ResolvedPath<'sg, LABEL, DATA>;
type IntoIter = <&'a HashSet<ResolvedPath<'sg, LABEL, DATA>> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}
impl<'sg, LABEL, DATA> IntoIterator for Env<'sg, LABEL, DATA> {
type Item = ResolvedPath<'sg, LABEL, DATA>;
type IntoIter = <HashSet<ResolvedPath<'sg, LABEL, DATA>> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl<LABEL, DATA> Default for Env<'_, LABEL, DATA> {
fn default() -> Self {
Self::new()
}
}
impl<'sg, LABEL, DATA> Env<'sg, LABEL, DATA> {
pub fn new() -> Self {
Self(HashSet::new())
}
pub fn iter<'a>(&'a self) -> impl Iterator<Item = &'a ResolvedPath<'sg, LABEL, DATA>> + 'a {
self.0.iter()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
pub enum OnlyElementError<'a, 'sg, DATA, LABEL, I>
where
I: Iterator<Item = &'a ResolvedPath<'sg, DATA, LABEL>>,
{
Empty,
Multiple {
first: &'a ResolvedPath<'sg, DATA, LABEL>,
second: &'a ResolvedPath<'sg, DATA, LABEL>,
rest: I,
},
}
impl<'a, 'sg, DATA, LABEL, I> Debug for OnlyElementError<'a, 'sg, DATA, LABEL, I>
where
I: Iterator<Item = &'a ResolvedPath<'sg, DATA, LABEL>>,
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
OnlyElementError::Empty => write!(f, "OnlyElementError::Empty"),
OnlyElementError::Multiple { .. } => {
write!(f, "OnlyElementError::Multiple {{..}}")
}
}
}
}
impl<'a, 'sg, DATA, LABEL, I> IntoIterator for OnlyElementError<'a, 'sg, DATA, LABEL, I>
where
I: Iterator<Item = &'a ResolvedPath<'sg, DATA, LABEL>>,
{
type Item = &'a ResolvedPath<'sg, DATA, LABEL>;
type IntoIter = OnlyElementErrorIter<'a, 'sg, DATA, LABEL, I>;
fn into_iter(self) -> Self::IntoIter {
OnlyElementErrorIter { e: self, offset: 0 }
}
}
pub struct OnlyElementErrorIter<'a, 'sg, DATA, LABEL, I>
where
I: Iterator<Item = &'a ResolvedPath<'sg, DATA, LABEL>>,
{
e: OnlyElementError<'a, 'sg, DATA, LABEL, I>,
offset: usize,
}
impl<'a, 'sg, DATA, LABEL, I> Iterator for OnlyElementErrorIter<'a, 'sg, DATA, LABEL, I>
where
I: Iterator<Item = &'a ResolvedPath<'sg, DATA, LABEL>>,
{
type Item = &'a ResolvedPath<'sg, DATA, LABEL>;
fn next(&mut self) -> Option<Self::Item> {
match &mut self.e {
OnlyElementError::Empty => None,
OnlyElementError::Multiple {
first,
second,
rest,
} => match self.offset {
0 => {
self.offset += 1;
Some(first)
}
1 => {
self.offset += 1;
Some(second)
}
_ => rest.next(),
},
}
}
}
impl<'sg, LABEL, DATA> Env<'sg, LABEL, DATA>
where
ResolvedPath<'sg, LABEL, DATA>: Eq + Hash + Clone,
{
pub fn single(path: ResolvedPath<'sg, LABEL, DATA>) -> Self {
let mut env = Env::new();
env.insert(path);
env
}
pub fn insert(&mut self, path: ResolvedPath<'sg, LABEL, DATA>) {
self.0.insert(path);
}
pub fn merge(&mut self, other: &Self) {
self.0.extend(other.0.iter().cloned())
}
#[allow(clippy::type_complexity)]
pub fn get_only_item<'a>(
&'a self,
) -> Result<
ResolvedPath<'sg, LABEL, DATA>,
OnlyElementError<
'a,
'sg,
LABEL,
DATA,
impl Iterator<Item = &'a ResolvedPath<'sg, LABEL, DATA>> + 'a,
>,
> {
let mut iter = self.iter();
iter.next().map_or(Err(OnlyElementError::Empty), |value| {
iter.next().map_or_else(
|| Ok(value.clone()),
|second| {
Err(OnlyElementError::Multiple {
first: value,
second,
rest: iter,
})
},
)
})
}
}
impl<'sg, LABEL: 'sg, DATA> FromIterator<ResolvedPath<'sg, LABEL, DATA>> for Env<'sg, LABEL, DATA>
where
ResolvedPath<'sg, LABEL, DATA>: Eq + Hash,
{
fn from_iter<T: IntoIterator<Item = ResolvedPath<'sg, LABEL, DATA>>>(iter: T) -> Self {
Env(HashSet::from_iter(iter))
}
}
impl<'sg, LABEL: 'sg, DATA: Hash> FromIterator<Env<'sg, LABEL, DATA>> for Env<'sg, LABEL, DATA>
where
ResolvedPath<'sg, LABEL, DATA>: Eq + Hash,
{
fn from_iter<T: IntoIterator<Item = Env<'sg, LABEL, DATA>>>(iter: T) -> Self {
iter.into_iter().flatten().collect()
}
}
impl<'sg, LABEL: 'sg + Clone, DATA> Clone for Env<'sg, LABEL, DATA> {
fn clone(&self) -> Self {
Env(self.0.clone())
}
}
pub trait Resolve<'sg, 'rslv> {
type EnvContainer
where
'sg: 'rslv,
Self: 'rslv;
fn resolve(&'rslv self, scope: Scope) -> Self::EnvContainer;
}
pub struct Query<'storage, 'sg, 'rslv, LABEL: Label, DATA, CMPL, PWF, DWF, LO, DEq> {
_phantom: PhantomData<&'rslv ()>,
scope_graph: &'sg ScopeGraph<'storage, LABEL, DATA, CMPL>,
path_wellformedness: PWF,
data_wellformedness: DWF,
label_order: LO,
data_equivalence: DEq,
}
impl<'sg, 'storage, 'rslv, LABEL: Label, DATA, CMPL, PWF, DWF, LO, DEq>
Query<'sg, 'storage, 'rslv, LABEL, DATA, CMPL, PWF, DWF, LO, DEq>
{
pub fn with_path_wellformedness<NPWF>(
self,
new_path_wellformedness: NPWF,
) -> Query<'sg, 'storage, 'rslv, LABEL, DATA, CMPL, NPWF, DWF, LO, DEq>
where
NPWF: for<'a> RegexMatcher<&'a LABEL> + 'rslv,
{
Query {
_phantom: PhantomData,
scope_graph: self.scope_graph,
path_wellformedness: new_path_wellformedness,
data_wellformedness: self.data_wellformedness,
label_order: self.label_order,
data_equivalence: self.data_equivalence,
}
}
pub fn with_data_wellformedness<NDWF>(
self,
new_data_wellformedness: NDWF,
) -> Query<'sg, 'storage, 'rslv, LABEL, DATA, CMPL, PWF, NDWF, LO, DEq>
where
NDWF: DataWellformedness<'sg, DATA> + 'rslv,
{
Query {
_phantom: PhantomData,
scope_graph: self.scope_graph,
path_wellformedness: self.path_wellformedness,
data_wellformedness: new_data_wellformedness,
label_order: self.label_order,
data_equivalence: self.data_equivalence,
}
}
pub fn with_label_order<NLO>(
self,
new_label_order: NLO,
) -> Query<'sg, 'storage, 'rslv, LABEL, DATA, CMPL, PWF, DWF, NLO, DEq>
where
NLO: LabelOrder<LABEL> + 'rslv,
{
Query {
_phantom: PhantomData,
scope_graph: self.scope_graph,
path_wellformedness: self.path_wellformedness,
data_wellformedness: self.data_wellformedness,
label_order: new_label_order,
data_equivalence: self.data_equivalence,
}
}
pub fn with_data_equivalence<NDEq>(
self,
new_data_equivalence: NDEq,
) -> Query<'sg, 'storage, 'rslv, LABEL, DATA, CMPL, PWF, DWF, LO, NDEq>
where
NDEq: DataEquivalence<'sg, DATA> + 'rslv,
{
Query {
_phantom: PhantomData,
scope_graph: self.scope_graph,
path_wellformedness: self.path_wellformedness,
data_wellformedness: self.data_wellformedness,
label_order: self.label_order,
data_equivalence: new_data_equivalence,
}
}
}
impl<'storage, LABEL: Label, DATA, CMPL> ScopeGraph<'storage, LABEL, DATA, CMPL> {
pub fn query<'rslv>(
&'rslv self,
) -> Query<
'storage,
'rslv,
'rslv, LABEL,
DATA,
CMPL,
(),
DefaultDataWellformedness,
DefaultLabelOrder,
DefaultDataEquivalence,
>
where
'storage: 'rslv,
{
Query {
_phantom: PhantomData,
scope_graph: self,
path_wellformedness: (),
data_wellformedness: DefaultDataWellformedness::default(),
label_order: DefaultLabelOrder::default(),
data_equivalence: DefaultDataEquivalence::default(),
}
}
}