use crate::value::key::Key;
use crate::value::parse;
use bstr::ByteSlice;
use serde::Deserialize;
use serde::Serialize;
use std::collections::VecDeque;
#[derive(Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(Serialize, Deserialize)]
pub struct Keys(Vec<Key>);
impl core::fmt::Debug for Keys {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self.0.is_empty() {
true => write!(f, "Keys([])"),
false => write!(f, "Keys(\"{self}\")"),
}
}
}
impl AsRef<[Key]> for Keys {
fn as_ref(&self) -> &[Key] {
&self.0
}
}
impl core::fmt::Display for Keys {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
if self.0.is_empty() {
return write!(f, ".");
}
let str = self
.0
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
.join(".");
f.write_str(&str)
}
}
impl<T: Into<Key>> From<T> for Keys {
fn from(value: T) -> Self {
Self(vec![value.into()])
}
}
impl<T: Into<Key>> From<Vec<T>> for Keys {
fn from(value: Vec<T>) -> Self {
Self(value.into_iter().map(Into::into).collect())
}
}
impl<T: Into<Key> + Clone> From<&[T]> for Keys {
fn from(value: &[T]) -> Self {
Self(value.iter().cloned().map(Into::into).collect())
}
}
impl TryFrom<Vec<Keys>> for Keys {
type Error = Vec<Keys>;
fn try_from(value: Vec<Keys>) -> Result<Self, Self::Error> {
match value.is_empty() {
false => Ok(Self(value.into_iter().flat_map(|a| a.0).collect())),
true => Err(value),
}
}
}
impl Keys {
pub fn parse(value: &[u8]) -> Self {
if value == b"." || value == b"" {
return Self(Vec::default());
}
let mut keys = value
.split_str(b".")
.filter(|k| !k.is_empty())
.map(Key::from)
.collect::<VecDeque<_>>();
if value.starts_with(b"...") {
keys.push_front(Key::from("..."));
} else if value.starts_with(b"..") {
keys.push_front(Key::from(".."));
}
Self(keys.into())
}
pub(crate) fn new(key: Vec<u8>) -> Self {
Self(vec![Key::new(key)])
}
pub(crate) fn into_vec(self) -> Vec<Key> {
self.0
}
pub fn as_slice(&self) -> &[Key] {
&self.0
}
pub fn as_usize(&self) -> Option<usize> {
match self.len() {
1 => self.0.first().and_then(|k| parse::usize(k.as_ref()).ok()),
_ => None,
}
}
pub fn get(&self, index: usize) -> Option<&Key> {
self.0.get(index)
}
pub fn first(&self) -> Option<&Key> {
self.0.first()
}
pub fn rest(&self) -> &[Key] {
self.0.get(1..).unwrap_or_default()
}
pub fn skip(&self, n: usize) -> &[Key] {
self.0.get(n..).unwrap_or_default()
}
pub fn without_first(mut self) -> Keys {
self.first().is_some().then(|| self.0.remove(0));
self
}
pub(crate) fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0 || self.0.iter().all(Key::is_empty)
}
pub(crate) fn is_placeholder(&self) -> bool {
self.len() == 1 && self.has_leading_placeholder()
}
pub(crate) fn has_leading_placeholder(&self) -> bool {
self.0.first().is_some_and(|k| k == b"_")
}
pub fn is_context_spread(&self) -> bool {
self.len() == 1 && self.is_spread()
}
pub fn is_partial_spread(&self) -> bool {
self.len() > 1 && self.is_spread()
}
pub(crate) fn is_spread(&self) -> bool {
self.0.first().is_some_and(|k| k == b"...")
}
pub fn is_parent(&self) -> bool {
self.0.first().is_some_and(|k| k == b"..")
}
pub fn fold<T: Into<Keys>>(mut self, other: T) -> Self {
self.0.append(&mut other.into().0);
self
}
pub fn join(mut self) -> Vec<u8> {
match self.0.len() {
0 => Vec::default(),
1 => self.0.remove(0).into(),
_ => self.to_string().into_bytes(),
}
}
pub fn is_match<T: AsRef<[u8]>>(&self, path: &[T]) -> bool {
self.0.len() == path.len() && self.is_prefix(path)
}
pub fn is_prefix<T: AsRef<[u8]>>(&self, path: &[T]) -> bool {
path.iter()
.enumerate()
.all(|(i, p)| self.0.get(i).is_some_and(|s| s == p))
}
}