use core::{convert::Infallible, iter::Fuse};
use crate::{ConstPathIter, DescendError, Internal, KeyError, Schema};
pub trait Key {
fn find(&self, internal: &Internal) -> Option<usize>;
}
impl<T: Key + ?Sized> Key for &T {
fn find(&self, internal: &Internal) -> Option<usize> {
(**self).find(internal)
}
}
impl<T: Key + ?Sized> Key for &mut T {
fn find(&self, internal: &Internal) -> Option<usize> {
(**self).find(internal)
}
}
pub trait Keys {
fn next(&mut self, internal: &Internal) -> Result<usize, KeyError>;
fn finalize(&mut self) -> Result<(), KeyError>;
}
impl<T: Keys + ?Sized> Keys for &mut T {
fn next(&mut self, internal: &Internal) -> Result<usize, KeyError> {
(**self).next(internal)
}
fn finalize(&mut self) -> Result<(), KeyError> {
(**self).finalize()
}
}
impl<T: Key> Keys for &[T] {
fn next(&mut self, internal: &Internal) -> Result<usize, KeyError> {
let (key, tail) = self.split_first().ok_or(KeyError::TooShort)?;
let index = key.find(internal).ok_or(KeyError::NotFound)?;
*self = tail;
Ok(index)
}
fn finalize(&mut self) -> Result<(), KeyError> {
if self.is_empty() {
Ok(())
} else {
Err(KeyError::TooLong)
}
}
}
pub trait IntoKeys {
type IntoKeys: Keys;
fn into_keys(self) -> Self::IntoKeys;
fn chain<U: IntoKeys>(self, other: U) -> Chain<Self::IntoKeys, U::IntoKeys>
where
Self: Sized,
{
Chain(self.into_keys(), other.into_keys())
}
}
pub trait Transcode {
type Error;
fn transcode_from(
&mut self,
schema: &Schema,
keys: impl Keys,
) -> Result<(), DescendError<Self::Error>>;
fn transcode(schema: &Schema, keys: impl IntoKeys) -> Result<Self, DescendError<Self::Error>>
where
Self: Sized + Default,
{
let mut target = Self::default();
target.transcode_from(schema, keys.into_keys())?;
Ok(target)
}
}
impl<T: Transcode + ?Sized> Transcode for &mut T {
type Error = T::Error;
fn transcode_from(
&mut self,
schema: &Schema,
keys: impl Keys,
) -> Result<(), DescendError<Self::Error>> {
(**self).transcode_from(schema, keys)
}
}
impl Transcode for () {
type Error = Infallible;
fn transcode_from(
&mut self,
schema: &Schema,
keys: impl Keys,
) -> Result<(), DescendError<Self::Error>> {
schema.descend(keys, |_, _| Ok::<_, Infallible>(()))
}
}
#[derive(Debug, Clone)]
#[repr(transparent)]
pub struct KeysIter<T>(Fuse<T>);
impl<T: Iterator> KeysIter<T> {
pub(crate) fn new(inner: T) -> Self {
Self(inner.fuse())
}
}
impl<T> Keys for KeysIter<T>
where
T: Iterator,
T::Item: Key,
{
fn next(&mut self, internal: &Internal) -> Result<usize, KeyError> {
let n = self.0.next().ok_or(KeyError::TooShort)?;
n.find(internal).ok_or(KeyError::NotFound)
}
fn finalize(&mut self) -> Result<(), KeyError> {
match self.0.next() {
Some(_) => Err(KeyError::TooLong),
None => Ok(()),
}
}
}
impl<'a> IntoKeys for &'a str {
type IntoKeys = ConstPathIter<'a, '/'>;
fn into_keys(self) -> Self::IntoKeys {
ConstPathIter::root(self)
}
}
impl<T: Key> IntoKeys for &[T] {
type IntoKeys = Self;
fn into_keys(self) -> Self::IntoKeys {
self
}
}
impl<'a, T: Key, const N: usize> IntoKeys for &'a [T; N] {
type IntoKeys = &'a [T];
fn into_keys(self) -> Self::IntoKeys {
&self[..]
}
}
impl<T: Key, const N: usize> IntoKeys for [T; N] {
type IntoKeys = KeysIter<core::array::IntoIter<T, N>>;
fn into_keys(self) -> Self::IntoKeys {
KeysIter::new(self.into_iter())
}
}
impl<T> IntoKeys for KeysIter<T>
where
T: Iterator,
T::Item: Key,
{
type IntoKeys = KeysIter<T>;
fn into_keys(self) -> Self::IntoKeys {
self
}
}
pub struct Chain<T, U>(T, U);
impl<T: Keys, U: Keys> Keys for Chain<T, U> {
fn next(&mut self, internal: &Internal) -> Result<usize, KeyError> {
match self.0.next(internal) {
Err(KeyError::TooShort) => self.1.next(internal),
ret => ret,
}
}
fn finalize(&mut self) -> Result<(), KeyError> {
self.0.finalize().and_then(|_| self.1.finalize())
}
}
impl<T: Keys, U: Keys> IntoKeys for Chain<T, U> {
type IntoKeys = Self;
fn into_keys(self) -> Self::IntoKeys {
self
}
}