use ahash::AHasher;
use std::fmt::{self, Debug, Display};
use std::hash::{Hash, Hasher};
use std::ops::Index;
use std::slice::Iter;
use std::sync::Arc;
use super::value::Value;
mod error;
mod id;
pub use error::{Error, Result};
pub use id::Id;
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Key<I> {
path: Arc<[I]>,
hash: u64,
}
impl<I> Key<I> {
#[inline]
pub fn try_as_id(&self) -> Result<&I> {
match &*self.path {
[id] => Ok(id),
[] => Err(Error::Empty),
_ => Err(Error::Depth),
}
}
}
impl<I> Key<I>
where
I: Id,
{
#[must_use]
pub fn concat<K>(&self, tail: K) -> Self
where
K: AsRef<Self>,
{
let tail = tail.as_ref();
let iter = self.path.iter().chain(tail.path.iter());
let path = iter.cloned().collect();
Self { hash: hash(&path), path }
}
#[must_use]
pub fn reverse(&self) -> Self {
let iter = self.path.iter().rev();
iter.cloned().collect()
}
#[must_use]
pub fn rotate_left(&self, n: usize) -> Self {
let iter = self.path[n..].iter().chain(self.path[..n].iter());
iter.cloned().collect()
}
#[inline]
#[must_use]
pub fn rotate_right(&self, n: usize) -> Self {
self.rotate_left(self.path.len() - n)
}
#[inline]
pub fn iter(&self) -> Iter<'_, I> {
self.path.iter()
}
}
impl<I> Value for Key<I> where I: Value {}
impl<I> AsRef<Key<I>> for Key<I> {
#[inline]
fn as_ref(&self) -> &Key<I> {
self
}
}
impl<I> From<I> for Key<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 Key<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<'a, I> IntoIterator for &'a Key<I>
where
I: Id,
{
type Item = &'a I;
type IntoIter = Iter<'a, I>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<I> Index<usize> for Key<I> {
type Output = I;
#[inline]
fn index(&self, index: usize) -> &Self::Output {
&self.path[index]
}
}
impl<I> Hash for Key<I> {
#[inline]
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
{
state.write_u64(self.hash);
}
}
impl<I> Display for Key<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 Key<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()
}