use crate::prelude::*;
pub struct Args<'slice> {
slice: &'slice [Value],
pos: usize,
}
impl<'slice> Args<'slice> {
#[inline]
#[must_use]
pub const fn new(slice: &'slice [Value]) -> Self {
Self { slice, pos: 0 }
}
#[inline]
pub fn next_owned(&mut self) -> Option<Value> {
self.next().cloned()
}
#[inline]
pub fn next_string(&mut self) -> Option<&'slice Arc<str>> {
match self.peek()? {
Value::String(s) => {
self.pos += 1;
Some(s)
}
_ => None,
}
}
#[inline]
pub fn next_string_owned(&mut self) -> Option<Arc<str>> {
self.next_string().cloned()
}
#[inline]
pub fn next_integer(&mut self) -> Option<i64> {
match self.peek()? {
Value::String(s) => {
if let Ok(i) = s.parse::<i64>() {
self.pos += 1;
Some(i)
} else {
None
}
}
Value::Integer(i) => {
self.pos += 1;
Some(*i)
}
_ => None,
}
}
#[inline]
#[must_use]
pub const fn len(&self) -> usize {
debug_assert!(self.pos <= self.slice.len(), "Args.pos is out of bounds");
self.slice.len() - self.pos
}
#[inline]
#[must_use]
pub const fn is_empty(&self) -> bool {
self.pos >= self.slice.len()
}
#[inline]
pub fn iter(&self) -> impl Iterator<Item = &'slice Value> {
self.into_iter()
}
#[inline]
#[must_use]
pub fn peek(&self) -> Option<&'slice Value> {
self.slice.get(self.pos)
}
}
impl std::fmt::Debug for Args<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_list().entries(self).finish()
}
}
impl<'slice> Iterator for Args<'slice> {
type Item = &'slice Value;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let value = self.slice.get(self.pos)?;
self.pos += 1;
Some(value)
}
#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.pos = self.pos.saturating_add(n);
let value = self.slice.get(self.pos)?;
self.pos += 1;
Some(value)
}
#[inline]
fn count(self) -> usize {
self.len()
}
#[inline]
fn last(mut self) -> Option<Self::Item> {
if !self.is_empty() {
self.pos = self.slice.len();
return self.slice.last();
}
None
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.len();
(remaining, Some(remaining))
}
}
impl<'slice> IntoIterator for &Args<'slice> {
type IntoIter = std::slice::Iter<'slice, Value>;
type Item = &'slice Value;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.slice[self.pos..].iter()
}
}