diff options
| author | Laurenz <laurmaedje@gmail.com> | 2021-08-12 13:39:33 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2021-08-12 13:56:23 +0200 |
| commit | eaa3cbaa9c2b1564a4b0db013672245a1893314a (patch) | |
| tree | 616a3d0f3686793caffcef72f230f8ba79b8f3ca /src/eval/array.rs | |
| parent | 8207c31aec6336b773fbf4661fdb87625c8b584e (diff) | |
Array and dictionary indexing
Diffstat (limited to 'src/eval/array.rs')
| -rw-r--r-- | src/eval/array.rs | 52 |
1 files changed, 32 insertions, 20 deletions
diff --git a/src/eval/array.rs b/src/eval/array.rs index 38876c96..356aa0ca 100644 --- a/src/eval/array.rs +++ b/src/eval/array.rs @@ -1,12 +1,14 @@ +use std::convert::TryFrom; use std::fmt::{self, Debug, Formatter}; 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. -#[macro_export] +#[allow(unused_macros)] macro_rules! array { ($value:expr; $count:expr) => { $crate::eval::Array::from_vec(vec![$crate::eval::Value::from($value); $count]) @@ -47,25 +49,25 @@ impl Array { } /// The length of the array. - pub fn len(&self) -> usize { - self.vec.len() + pub fn len(&self) -> i64 { + self.vec.len() as i64 } /// Borrow the value at the given index. - pub fn get(&self, index: usize) -> Option<&Value> { - self.vec.get(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: usize) -> Option<&mut Value> { - Rc::make_mut(&mut self.vec).get_mut(index) - } - - /// Set the value at the given index. - /// - /// This panics the `index` is out of range. - pub fn set(&mut self, index: usize, value: Value) { - Rc::make_mut(&mut self.vec)[index] = value; + 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. @@ -82,16 +84,26 @@ impl Array { } } - /// Repeat this array `n` times. - pub fn repeat(&self, n: usize) -> Self { - let len = self.len().checked_mul(n).expect("capacity overflow"); - self.iter().cloned().cycle().take(len).collect() - } - /// Iterate over references to the contained values. pub fn iter(&self) -> std::slice::Iter<Value> { self.vec.iter() } + + /// Repeat this array `n` times. + pub fn repeat(&self, n: i64) -> StrResult<Self> { + 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 Default for Array { |
