use std::{
fmt,
num::NonZeroUsize,
string::ToString,
};
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct Index(pub(crate) usize);
impl Index {
#[must_use]
pub fn new(index: usize) -> Index {
Index(index)
}
}
impl From<Index> for usize {
fn from(index: Index) -> usize {
index.0
}
}
impl fmt::Display for Index {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Index ({})", self.0)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Range(pub(crate) Option<Index>, pub(crate) Option<Index>);
impl Range {
#[must_use]
pub fn new(start: Option<Index>, end: Option<Index>) -> Range {
Range(start, end)
}
#[must_use]
pub fn to_boundaries(&self, len: NonZeroUsize) -> (usize, usize) {
let start = self.0.unwrap_or(Index(0));
let end = self.1.unwrap_or(Index(len.get() - 1));
(start.0, end.0)
}
}
impl fmt::Display for Range {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let format_bound = |bound: &Option<Index>| match bound {
Some(index) => index.to_string(),
None => String::new(),
};
write!(
f,
"Range [{}:{}]",
format_bound(&self.0),
format_bound(&self.1)
)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Lens<'a>(pub(crate) &'a str, pub(crate) Option<LensValue<'a>>);
impl<'a> Lens<'a> {
#[must_use]
pub fn new(key: &'a str, value: Option<LensValue<'a>>) -> Lens<'a> {
Lens(key, value)
}
#[must_use]
pub fn get(&self) -> (&'a str, Option<LensValue<'a>>) {
(self.0, self.1.clone())
}
}
impl<'a> fmt::Display for Lens<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{}{}",
self.0,
match &self.1 {
Some(lens_value) => {
lens_value.to_string()
}
None => String::new(),
}
)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum LensValue<'a> {
Bool(bool),
Null,
Number(usize),
String(&'a str),
}
impl<'a> fmt::Display for LensValue<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
LensValue::Bool(boolean) => {
write!(f, "{boolean}")
}
LensValue::Null => {
write!(f, "null")
}
LensValue::Number(number) => {
write!(f, "{number}")
}
LensValue::String(string) => write!(f, "{string}"),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Token<'a> {
ArrayIndexSelector(Vec<Index>),
ArrayRangeSelector(Range),
FlattenOperator,
GroupSeparator,
KeySelector(&'a str),
LensSelector(Vec<Lens<'a>>),
MultiKeySelector(Vec<&'a str>),
ObjectIndexSelector(Vec<Index>),
ObjectRangeSelector(Range),
PipeInOperator,
PipeOutOperator,
TruncateOperator,
}
impl<'a> Token<'a> {
fn get_name(&self) -> &'a str {
match self {
Token::ArrayIndexSelector(_) => "Array Index Selector",
Token::ArrayRangeSelector(_) => "Array Range Selector",
Token::FlattenOperator => "Flatten Operator",
Token::GroupSeparator => "Group Separator",
Token::KeySelector(_) => "Key Selector",
Token::LensSelector(_) => "Lens Selector",
Token::MultiKeySelector(_) => "Multi Key Selector",
Token::ObjectIndexSelector(_) => "Object Index Selector",
Token::ObjectRangeSelector(_) => "Object Range Selector",
Token::PipeInOperator => "Pipe In Operator",
Token::PipeOutOperator => "Pipe Out Operator",
Token::TruncateOperator => "Truncate Operator",
}
}
}
impl<'a> fmt::Display for Token<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Token::ArrayIndexSelector(indexes) | Token::ObjectIndexSelector(indexes) => {
let formatted_indexes = indexes
.iter()
.map(ToString::to_string)
.collect::<Vec<String>>()
.join(", ");
write!(f, "{} [{formatted_indexes}]", self.get_name())
}
Token::ArrayRangeSelector(range) | Token::ObjectRangeSelector(range) => {
write!(f, "{} {}", self.get_name(), range)
}
Token::KeySelector(key) => {
write!(f, r#"{} "{key}""#, self.get_name())
}
Token::LensSelector(lenses) => {
let formatted_indexes = lenses
.iter()
.map(ToString::to_string)
.collect::<Vec<String>>()
.join(", ");
write!(f, "{} [{formatted_indexes}]", self.get_name())
}
Token::MultiKeySelector(multi_key) => {
let formatted_keys = multi_key.join(", ");
write!(f, "{} {formatted_keys}", self.get_name())
}
Token::FlattenOperator
| Token::GroupSeparator
| Token::PipeInOperator
| Token::PipeOutOperator
| Token::TruncateOperator => {
write!(f, "{}", self.get_name())
}
}
}
}
pub trait View {
fn stringify(&self) -> String;
}
impl<'a, T: AsRef<[Token<'a>]>> View for T {
fn stringify(&self) -> String {
self.as_ref()
.iter()
.map(ToString::to_string)
.collect::<Vec<String>>()
.join(", ")
}
}