use std::iter::FromIterator;
use std::mem;
use crate::repr::Decor;
use crate::value::{DEFAULT_LEADING_VALUE_DECOR, DEFAULT_VALUE_DECOR};
use crate::{InternalString, Item, Value};
#[derive(Debug, Default, Clone)]
pub struct Array {
trailing: InternalString,
trailing_comma: bool,
decor: Decor,
pub(crate) values: Vec<Item>,
}
pub type ArrayIntoIter = Box<dyn Iterator<Item = Value>>;
pub type ArrayIter<'a> = Box<dyn Iterator<Item = &'a Value> + 'a>;
pub type ArrayIterMut<'a> = Box<dyn Iterator<Item = &'a mut Value> + 'a>;
impl Array {
pub fn new() -> Self {
Default::default()
}
pub(crate) fn with_vec(values: Vec<Item>) -> Self {
Self {
values,
..Default::default()
}
}
}
impl Array {
pub fn fmt(&mut self) {
decorate_array(self);
}
pub fn set_trailing_comma(&mut self, yes: bool) {
self.trailing_comma = yes;
}
pub fn trailing_comma(&self) -> bool {
self.trailing_comma
}
pub fn set_trailing(&mut self, trailing: &str) {
self.trailing = InternalString::from(trailing);
}
pub fn trailing(&self) -> &str {
self.trailing.as_str()
}
pub fn decor_mut(&mut self) -> &mut Decor {
&mut self.decor
}
pub fn decor(&self) -> &Decor {
&self.decor
}
}
impl Array {
pub fn iter(&self) -> ArrayIter<'_> {
Box::new(self.values.iter().filter_map(Item::as_value))
}
pub fn iter_mut(&mut self) -> ArrayIterMut<'_> {
Box::new(self.values.iter_mut().filter_map(Item::as_value_mut))
}
pub fn len(&self) -> usize {
self.values.len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn clear(&mut self) {
self.values.clear()
}
pub fn get(&self, index: usize) -> Option<&Value> {
self.values.get(index).and_then(Item::as_value)
}
pub fn get_mut(&mut self, index: usize) -> Option<&mut Value> {
self.values.get_mut(index).and_then(Item::as_value_mut)
}
pub fn push<V: Into<Value>>(&mut self, v: V) {
self.value_op(v.into(), true, |items, value| {
items.push(Item::Value(value))
})
}
pub fn push_formatted(&mut self, v: Value) {
self.values.push(Item::Value(v));
}
pub fn insert<V: Into<Value>>(&mut self, index: usize, v: V) {
self.value_op(v.into(), true, |items, value| {
items.insert(index, Item::Value(value))
})
}
pub fn insert_formatted(&mut self, index: usize, v: Value) {
self.values.insert(index, Item::Value(v))
}
pub fn replace<V: Into<Value>>(&mut self, index: usize, v: V) -> Value {
let existing_decor = self
.get(index)
.unwrap_or_else(|| panic!("index {} out of bounds (len = {})", index, self.len()))
.decor();
let mut value = v.into();
*value.decor_mut() = existing_decor.clone();
self.replace_formatted(index, value)
}
pub fn replace_formatted(&mut self, index: usize, v: Value) -> Value {
match mem::replace(&mut self.values[index], Item::Value(v)) {
Item::Value(old_value) => old_value,
x => panic!("non-value item {:?} in an array", x),
}
}
pub fn remove(&mut self, index: usize) -> Value {
let removed = self.values.remove(index);
match removed {
Item::Value(v) => v,
x => panic!("non-value item {:?} in an array", x),
}
}
fn value_op<T>(
&mut self,
v: Value,
decorate: bool,
op: impl FnOnce(&mut Vec<Item>, Value) -> T,
) -> T {
let mut value = v;
if !self.is_empty() && decorate {
value.decorate(" ", "");
} else if decorate {
value.decorate("", "");
}
op(&mut self.values, value)
}
}
impl std::fmt::Display for Array {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
crate::encode::Encode::encode(self, f, ("", ""))
}
}
impl<V: Into<Value>> Extend<V> for Array {
fn extend<T: IntoIterator<Item = V>>(&mut self, iter: T) {
for value in iter {
self.push_formatted(value.into());
}
}
}
impl<V: Into<Value>> FromIterator<V> for Array {
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = V>,
{
let v = iter.into_iter().map(|a| Item::Value(a.into()));
Array {
values: v.collect(),
..Default::default()
}
}
}
impl IntoIterator for Array {
type Item = Value;
type IntoIter = ArrayIntoIter;
fn into_iter(self) -> Self::IntoIter {
Box::new(
self.values
.into_iter()
.filter(|v| v.is_value())
.map(|v| v.into_value().unwrap()),
)
}
}
impl<'s> IntoIterator for &'s Array {
type Item = &'s Value;
type IntoIter = ArrayIter<'s>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
fn decorate_array(array: &mut Array) {
for (i, value) in array
.values
.iter_mut()
.filter_map(Item::as_value_mut)
.enumerate()
{
if i == 0 {
value.decorate(DEFAULT_LEADING_VALUE_DECOR.0, DEFAULT_LEADING_VALUE_DECOR.1);
} else {
value.decorate(DEFAULT_VALUE_DECOR.0, DEFAULT_VALUE_DECOR.1);
}
}
}