use crate::path::OwnedSegment;
use crate::value::kind::Collection;
use crate::value::kind::collection::{CollectionKey, CollectionRemove};
#[derive(Debug, Clone, Default, Copy, Eq, PartialEq, PartialOrd, Ord, Hash)]
pub struct Index(usize);
impl std::fmt::Display for Index {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
impl Index {
#[must_use]
pub const fn to_usize(self) -> usize {
self.0
}
}
impl CollectionKey for Index {
fn to_segment(&self) -> OwnedSegment {
OwnedSegment::Index(self.0 as isize)
}
}
impl Collection<Index> {
#[must_use]
pub fn largest_known_index(&self) -> Option<usize> {
self.known()
.iter()
.filter_map(|(i, kind)| {
if kind.contains_any_defined() {
Some(i.to_usize())
} else {
None
}
})
.max()
}
#[must_use]
pub fn get_positive_index(&self, index: isize) -> Option<usize> {
if self.unknown_kind().contains_any_defined() {
return None;
}
let negative_index = (-index) as usize;
if let Some(largest_known_index) = self.largest_known_index()
&& largest_known_index >= negative_index - 1
{
return Some(((largest_known_index as isize) + 1 + index) as usize);
}
None
}
#[must_use]
pub fn min_length(&self) -> usize {
self.largest_known_index().map_or(0, |i| i + 1)
}
#[must_use]
pub fn exact_length(&self) -> Option<usize> {
if self.unknown_kind().contains_any_defined() {
None
} else {
Some(self.min_length())
}
}
pub fn remove_shift(&mut self, index: usize) {
let min_length = self.min_length();
self.known_mut().remove(&index.into());
for _ in index..min_length {
if let Some(value) = self.known_mut().remove(&(index + 1).into()) {
self.known_mut().insert(index.into(), value);
}
}
}
}
impl CollectionRemove for Collection<Index> {
type Key = Index;
fn remove_known(&mut self, key: &Index) {
self.remove_shift(key.0);
}
}
impl From<usize> for Index {
fn from(index: usize) -> Self {
(&index).into()
}
}
impl From<&usize> for Index {
fn from(index: &usize) -> Self {
Self(*index)
}
}
impl From<Index> for usize {
fn from(index: Index) -> Self {
(&index).into()
}
}
impl From<&Index> for usize {
fn from(index: &Index) -> Self {
index.0
}
}
impl<T: Into<Self>> std::ops::Add<T> for Index {
type Output = Self;
fn add(self, other: T) -> Self {
Self(self.0 + other.into().0)
}
}
impl<T: Into<Self>> std::ops::Sub<T> for Index {
type Output = Self;
fn sub(self, other: T) -> Self {
Self(self.0 - other.into().0)
}
}