use ahash::AHasher;
use std::fmt::{self, Debug, Display};
use std::hash::{Hash, Hasher};
use std::ops::Index;
use std::sync::Arc;
use super::value::Value;
use super::Id;
mod error;
pub use error::{Error, Result};
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Scope<I> {
path: Arc<[I]>,
hash: u64,
}
impl<I> Scope<I> {
#[inline]
pub fn try_as_id(&self) -> Result<&I> {
match &*self.path {
[id] => Ok(id),
[] => Err(Error::Empty),
_ => Err(Error::Depth),
}
}
}
impl<I> Scope<I>
where
I: Id,
{
#[must_use]
pub fn concat(&self, other: &Self) -> Self {
let iter = self.path.iter().chain(other.path.iter());
let path = iter.cloned().collect();
Self { hash: hash(&path), path }
}
#[must_use]
pub fn reverse(&self) -> Self {
let mut path = self.path.to_vec();
path.reverse();
Self {
hash: hash(&path),
path: Arc::from(path),
}
}
#[must_use]
pub fn rotate_left(&self, n: usize) -> Self {
let mut path = self.path.to_vec();
path.rotate_left(n);
Self {
hash: hash(&path),
path: Arc::from(path),
}
}
#[must_use]
pub fn rotate_right(&self, n: usize) -> Self {
let mut path = self.path.to_vec();
path.rotate_right(n);
Self {
hash: hash(&path),
path: Arc::from(path),
}
}
}
impl<I> Value for Scope<I> where I: Value {}
impl<I> From<I> for Scope<I>
where
I: Id,
{
#[inline]
fn from(id: I) -> Self {
let path = Arc::from([id]);
Self { hash: hash(&path), path }
}
}
impl<I> FromIterator<I> for Scope<I>
where
I: Id,
{
fn from_iter<T>(iter: T) -> Self
where
T: IntoIterator<Item = I>,
{
let path = iter.into_iter().collect();
Self { hash: hash(&path), path }
}
}
impl<I> Index<usize> for Scope<I> {
type Output = I;
#[inline]
fn index(&self, index: usize) -> &Self::Output {
&self.path[index]
}
}
impl<I> Hash for Scope<I> {
#[inline]
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
{
state.write_u64(self.hash);
}
}
impl<I> Display for Scope<I>
where
I: Display,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for (i, item) in self.path.iter().enumerate() {
Display::fmt(item, f)?;
if i < self.path.len() - 1 {
f.write_str(" / ")?;
}
}
Ok(())
}
}
impl<I> Debug for Scope<I>
where
I: Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_list().entry(&self.path).finish()
}
}
#[inline]
fn hash<P>(path: &P) -> u64
where
P: Hash,
{
let mut hasher = AHasher::default();
path.hash(&mut hasher);
hasher.finish()
}