Generic casting for Axes<T>

This commit is contained in:
Laurenz 2025-06-19 17:20:17 +02:00
parent 3b35f0cecf
commit d821633f50
4 changed files with 38 additions and 33 deletions

View File

@ -4,9 +4,12 @@ use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Deref, Not};
use typst_utils::Get;
use crate::diag::bail;
use crate::foundations::{array, cast, Array, Resolve, Smart, StyleChain};
use crate::layout::{Abs, Dir, Length, Ratio, Rel, Size};
use crate::diag::{bail, HintedStrResult};
use crate::foundations::{
array, cast, Array, CastInfo, FromValue, IntoValue, Reflect, Resolve, Smart,
StyleChain, Value,
};
use crate::layout::{Abs, Dir, Rel, Size};
/// A container with a horizontal and vertical component.
#[derive(Default, Copy, Clone, Eq, PartialEq, Hash)]
@ -275,40 +278,39 @@ impl BitAndAssign for Axes<bool> {
}
}
cast! {
Axes<Rel<Length>>,
self => array![self.x, self.y].into_value(),
array: Array => {
let mut iter = array.into_iter();
match (iter.next(), iter.next(), iter.next()) {
(Some(a), Some(b), None) => Axes::new(a.cast()?, b.cast()?),
_ => bail!("point array must contain exactly two entries"),
impl<T: Reflect> Reflect for Axes<T> {
fn input() -> CastInfo {
Array::input()
}
fn output() -> CastInfo {
Array::output()
}
fn castable(value: &Value) -> bool {
Array::castable(value)
}
},
}
cast! {
Axes<Ratio>,
self => array![self.x, self.y].into_value(),
array: Array => {
impl<T: FromValue> FromValue for Axes<T> {
fn from_value(value: Value) -> HintedStrResult<Self> {
let array = value.cast::<Array>()?;
let mut iter = array.into_iter();
match (iter.next(), iter.next(), iter.next()) {
(Some(a), Some(b), None) => Axes::new(a.cast()?, b.cast()?),
_ => bail!("ratio array must contain exactly two entries"),
(Some(a), Some(b), None) => Ok(Axes::new(a.cast()?, b.cast()?)),
_ => bail!(
"array must contain exactly two items";
hint: "the first item determines the value for the X axis \
and the second item the value for the Y axis"
),
}
}
},
}
cast! {
Axes<Length>,
self => array![self.x, self.y].into_value(),
array: Array => {
let mut iter = array.into_iter();
match (iter.next(), iter.next(), iter.next()) {
(Some(a), Some(b), None) => Axes::new(a.cast()?, b.cast()?),
_ => bail!("length array must contain exactly two entries"),
impl<T: IntoValue> IntoValue for Axes<T> {
fn into_value(self) -> Value {
array![self.x.into_value(), self.y.into_value()].into_value()
}
},
}
impl<T: Resolve> Resolve for Axes<T> {

View File

@ -84,7 +84,8 @@
--- line-bad-point-array ---
// Test errors.
// Error: 12-19 point array must contain exactly two entries
// Error: 12-19 array must contain exactly two items
// Hint: 12-19 the first item determines the value for the X axis and the second item the value for the Y axis
#line(end: (50pt,))
--- line-bad-point-component-type ---

View File

@ -76,7 +76,8 @@
#path(((0%, 0%), (0%, 0%), (0%, 0%), (0%, 0%)))
--- path-bad-point-array ---
// Error: 7-31 point array must contain exactly two entries
// Error: 7-31 array must contain exactly two items
// Hint: 7-31 the first item determines the value for the X axis and the second item the value for the Y axis
// Warning: 2-6 the `path` function is deprecated, use `curve` instead
#path(((0%, 0%), (0%, 0%, 0%)))

View File

@ -49,7 +49,8 @@
)
--- polygon-bad-point-array ---
// Error: 10-17 point array must contain exactly two entries
// Error: 10-17 array must contain exactly two items
// Hint: 10-17 the first item determines the value for the X axis and the second item the value for the Y axis
#polygon((50pt,))
--- polygon-infinite-size ---