use std::convert::TryFrom; use std::fmt::{self, Debug, Display, Formatter, Write}; use std::iter::FromIterator; use std::ops::{Add, AddAssign}; use std::rc::Rc; use super::Value; use crate::diag::StrResult; /// Create a new [`Array`] from values. #[allow(unused_macros)] macro_rules! array { ($value:expr; $count:expr) => { $crate::eval::Array::from_vec(vec![$crate::eval::Value::from($value); $count]) }; ($($value:expr),* $(,)?) => { $crate::eval::Array::from_vec(vec![$($crate::eval::Value::from($value)),*]) }; } /// An array of values with clone-on-write value semantics. #[derive(Default, Clone, PartialEq)] pub struct Array { vec: Rc>, } impl Array { /// Create a new, empty array. pub fn new() -> Self { Self::default() } /// Create a new array from a vector of values. pub fn from_vec(vec: Vec) -> Self { Self { vec: Rc::new(vec) } } /// Whether the array is empty. pub fn is_empty(&self) -> bool { self.vec.is_empty() } /// The length of the array. pub fn len(&self) -> i64 { self.vec.len() as i64 } /// Borrow the value at the given index. pub fn get(&self, index: i64) -> StrResult<&Value> { usize::try_from(index) .ok() .and_then(|i| self.vec.get(i)) .ok_or_else(|| out_of_bounds(index, self.len())) } /// Mutably borrow the value at the given index. pub fn get_mut(&mut self, index: i64) -> StrResult<&mut Value> { let len = self.len(); usize::try_from(index) .ok() .and_then(move |i| Rc::make_mut(&mut self.vec).get_mut(i)) .ok_or_else(|| out_of_bounds(index, len)) } /// Push a value to the end of the array. pub fn push(&mut self, value: Value) { Rc::make_mut(&mut self.vec).push(value); } /// Clear the array. pub fn clear(&mut self) { if Rc::strong_count(&mut self.vec) == 1 { Rc::make_mut(&mut self.vec).clear(); } else { *self = Self::new(); } } /// Iterate over references to the contained values. pub fn iter(&self) -> std::slice::Iter { self.vec.iter() } /// Repeat this array `n` times. pub fn repeat(&self, n: i64) -> StrResult { let count = usize::try_from(n) .ok() .and_then(|n| self.vec.len().checked_mul(n)) .ok_or_else(|| format!("cannot repeat this array {} times", n))?; Ok(self.iter().cloned().cycle().take(count).collect()) } } /// The out of bounds access error message. #[cold] fn out_of_bounds(index: i64, len: i64) -> String { format!("array index out of bounds (index: {}, len: {})", index, len) } impl Debug for Array { fn fmt(&self, f: &mut Formatter) -> fmt::Result { f.debug_list().entries(self.vec.iter()).finish() } } impl Display for Array { fn fmt(&self, f: &mut Formatter) -> fmt::Result { f.write_char('(')?; for (i, value) in self.iter().enumerate() { Display::fmt(value, f)?; if i + 1 < self.vec.len() { f.write_str(", ")?; } } if self.len() == 1 { f.write_char(',')?; } f.write_char(')') } } impl Add for Array { type Output = Self; fn add(mut self, rhs: Array) -> Self::Output { self += rhs; self } } impl AddAssign for Array { fn add_assign(&mut self, rhs: Array) { match Rc::try_unwrap(rhs.vec) { Ok(vec) => self.extend(vec), Err(rc) => self.extend(rc.iter().cloned()), } } } impl FromIterator for Array { fn from_iter>(iter: T) -> Self { Array { vec: Rc::new(iter.into_iter().collect()) } } } impl Extend for Array { fn extend>(&mut self, iter: T) { Rc::make_mut(&mut self.vec).extend(iter); } } impl IntoIterator for Array { type Item = Value; type IntoIter = std::vec::IntoIter; fn into_iter(self) -> Self::IntoIter { match Rc::try_unwrap(self.vec) { Ok(vec) => vec.into_iter(), Err(rc) => (*rc).clone().into_iter(), } } } impl<'a> IntoIterator for &'a Array { type Item = &'a Value; type IntoIter = std::slice::Iter<'a, Value>; fn into_iter(self) -> Self::IntoIter { self.iter() } }