summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/typst/src/foundations/array.rs32
-rw-r--r--tests/typ/compiler/array.typ20
2 files changed, 51 insertions, 1 deletions
diff --git a/crates/typst/src/foundations/array.rs b/crates/typst/src/foundations/array.rs
index 1df24bd8..a1e93d7b 100644
--- a/crates/typst/src/foundations/array.rs
+++ b/crates/typst/src/foundations/array.rs
@@ -1,6 +1,6 @@
use std::cmp::Ordering;
use std::fmt::{Debug, Formatter};
-use std::num::NonZeroI64;
+use std::num::{NonZeroI64, NonZeroUsize};
use std::ops::{Add, AddAssign};
use ecow::{eco_format, EcoString, EcoVec};
@@ -724,6 +724,36 @@ impl Array {
Array(vec)
}
+ /// Splits an array into non-overlapping chunks, starting at the beginning,
+ /// ending with a single remainder chunk.
+ ///
+ /// All chunks but the last have `chunk-size` elements.
+ /// If `exact` is set to `{true}`, the remainder is dropped if it
+ /// contains less than `chunk-size` elements.
+ ///
+ /// ```example
+ /// #let array = (1, 2, 3, 4, 5, 6, 7, 8)
+ /// #array.chunks(3)
+ /// #array.chunks(3, exact: true)
+ /// ```
+ #[func]
+ pub fn chunks(
+ self,
+ /// How many elements each chunk may at most contain.
+ chunk_size: NonZeroUsize,
+ /// Whether to keep the remainder if its size is less than `chunk-size`.
+ #[named]
+ #[default(false)]
+ exact: bool,
+ ) -> Array {
+ let to_array = |chunk| Array::from(chunk).into_value();
+ if exact {
+ self.0.chunks_exact(chunk_size.get()).map(to_array).collect()
+ } else {
+ self.0.chunks(chunk_size.get()).map(to_array).collect()
+ }
+ }
+
/// Return a sorted version of this array, optionally by a given key
/// function. The sorting algorithm used is stable.
///
diff --git a/tests/typ/compiler/array.typ b/tests/typ/compiler/array.typ
index 9ff29480..4a1948ff 100644
--- a/tests/typ/compiler/array.typ
+++ b/tests/typ/compiler/array.typ
@@ -237,6 +237,26 @@
#test((1, 2, "b").intersperse("a"), (1, "a", 2, "a", "b"))
---
+// Test the `chunks` method.
+#test(().chunks(10), ())
+#test((1, 2, 3).chunks(10), ((1, 2, 3),))
+#test((1, 2, 3, 4, 5, 6).chunks(3), ((1, 2, 3), (4, 5, 6)))
+#test((1, 2, 3, 4, 5, 6, 7, 8).chunks(3), ((1, 2, 3), (4, 5, 6), (7, 8)))
+
+#test(().chunks(10, exact: true), ())
+#test((1, 2, 3).chunks(10, exact: true), ())
+#test((1, 2, 3, 4, 5, 6).chunks(3, exact: true), ((1, 2, 3), (4, 5, 6)))
+#test((1, 2, 3, 4, 5, 6, 7, 8).chunks(3, exact: true), ((1, 2, 3), (4, 5, 6)))
+
+---
+// Error: 19-20 number must be positive
+#(1, 2, 3).chunks(0)
+
+---
+// Error: 19-21 number must be positive
+#(1, 2, 3).chunks(-5)
+
+---
// Test the `sorted` method.
#test(().sorted(), ())
#test(().sorted(key: x => x), ())