mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
Negative array indexing
This commit is contained in:
parent
cd62792c0a
commit
1101a8370f
@ -48,8 +48,7 @@ impl Array {
|
||||
|
||||
/// Borrow the value at the given index.
|
||||
pub fn get(&self, index: i64) -> StrResult<&Value> {
|
||||
usize::try_from(index)
|
||||
.ok()
|
||||
self.locate(index)
|
||||
.and_then(|i| self.0.get(i))
|
||||
.ok_or_else(|| out_of_bounds(index, self.len()))
|
||||
}
|
||||
@ -57,8 +56,7 @@ impl Array {
|
||||
/// 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()
|
||||
self.locate(index)
|
||||
.and_then(move |i| Arc::make_mut(&mut self.0).get_mut(i))
|
||||
.ok_or_else(|| out_of_bounds(index, len))
|
||||
}
|
||||
@ -77,8 +75,8 @@ impl Array {
|
||||
/// Insert a value at the specified index.
|
||||
pub fn insert(&mut self, index: i64, value: Value) -> StrResult<()> {
|
||||
let len = self.len();
|
||||
let i = usize::try_from(index)
|
||||
.ok()
|
||||
let i = self
|
||||
.locate(index)
|
||||
.filter(|&i| i <= self.0.len())
|
||||
.ok_or_else(|| out_of_bounds(index, len))?;
|
||||
|
||||
@ -89,8 +87,8 @@ impl Array {
|
||||
/// Remove and return the value at the specified index.
|
||||
pub fn remove(&mut self, index: i64) -> StrResult<()> {
|
||||
let len = self.len();
|
||||
let i = usize::try_from(index)
|
||||
.ok()
|
||||
let i = self
|
||||
.locate(index)
|
||||
.filter(|&i| i < self.0.len())
|
||||
.ok_or_else(|| out_of_bounds(index, len))?;
|
||||
|
||||
@ -106,16 +104,17 @@ impl Array {
|
||||
/// Extract a contigous subregion of the array.
|
||||
pub fn slice(&self, start: i64, end: Option<i64>) -> StrResult<Self> {
|
||||
let len = self.len();
|
||||
let start = usize::try_from(start)
|
||||
.ok()
|
||||
let start = self
|
||||
.locate(start)
|
||||
.filter(|&start| start <= self.0.len())
|
||||
.ok_or_else(|| out_of_bounds(start, len))?;
|
||||
|
||||
let end = end.unwrap_or(self.len());
|
||||
let end = usize::try_from(end)
|
||||
.ok()
|
||||
let end = self
|
||||
.locate(end)
|
||||
.filter(|&end| end <= self.0.len())
|
||||
.ok_or_else(|| out_of_bounds(end, len))?;
|
||||
.ok_or_else(|| out_of_bounds(end, len))?
|
||||
.max(start);
|
||||
|
||||
Ok(Self::from_vec(self.0[start .. end].to_vec()))
|
||||
}
|
||||
@ -225,11 +224,20 @@ impl Array {
|
||||
self.0.as_slice()
|
||||
}
|
||||
|
||||
|
||||
/// Iterate over references to the contained values.
|
||||
pub fn iter(&self) -> std::slice::Iter<Value> {
|
||||
self.0.iter()
|
||||
}
|
||||
|
||||
/// Resolve an index.
|
||||
fn locate(&self, index: i64) -> Option<usize> {
|
||||
usize::try_from(if index >= 0 {
|
||||
index
|
||||
} else {
|
||||
self.len().checked_add(index)?
|
||||
})
|
||||
.ok()
|
||||
}
|
||||
}
|
||||
|
||||
/// The out of bounds access error message.
|
||||
|
@ -31,20 +31,32 @@
|
||||
|
||||
---
|
||||
// Test rvalue out of bounds.
|
||||
{
|
||||
let array = (1, 2, 3)
|
||||
// Error: 3-11 array index out of bounds (index: 5, len: 3)
|
||||
array(5)
|
||||
}
|
||||
// Error: 2-14 array index out of bounds (index: 5, len: 3)
|
||||
{(1, 2, 3)(5)}
|
||||
|
||||
---
|
||||
// Test lvalue out of bounds.
|
||||
{
|
||||
let array = (1, 2, 3)
|
||||
// Error: 3-12 array index out of bounds (index: -1, len: 3)
|
||||
array(-1) = 5
|
||||
// Error: 3-11 array index out of bounds (index: 3, len: 3)
|
||||
array(3) = 5
|
||||
}
|
||||
|
||||
---
|
||||
// Test negative indices.
|
||||
{
|
||||
let array = (1, 2, 3, 4)
|
||||
test(array(0), 1)
|
||||
test(array(-1), 4)
|
||||
test(array(-2), 3)
|
||||
test(array(-3), 2)
|
||||
test(array(-4), 1)
|
||||
}
|
||||
|
||||
---
|
||||
// Error: 2-15 array index out of bounds (index: -4, len: 3)
|
||||
{(1, 2, 3)(-4)}
|
||||
|
||||
---
|
||||
// Test non-collection indexing.
|
||||
|
||||
|
@ -38,11 +38,19 @@
|
||||
#test((1, 2, 3, 4).slice(2), (3, 4))
|
||||
#test(range(10).slice(2, 6), (2, 3, 4, 5))
|
||||
#test(range(10).slice(4, count: 3), (4, 5, 6))
|
||||
#test((1, 2, 3).slice(2, -2), ())
|
||||
#test((1, 2, 3).slice(-2, 2), (2,))
|
||||
#test((1, 2, 3).slice(-3, 2), (1, 2))
|
||||
#test("ABCD".split("").slice(1, -1).join("-"), "A-B-C-D")
|
||||
|
||||
---
|
||||
// Error: 3-31 array index out of bounds (index: 12, len: 10)
|
||||
{ range(10).slice(9, count: 3) }
|
||||
|
||||
---
|
||||
// Error: 3-25 array index out of bounds (index: -4, len: 3)
|
||||
{ (1, 2, 3).slice(0, -4) }
|
||||
|
||||
---
|
||||
// Error: 2:17-2:19 missing argument: index
|
||||
#let numbers = ()
|
||||
|
Loading…
x
Reference in New Issue
Block a user