Repository: typst/typst
File: crates/typst/src/layout/align.rs (Rust)

Code before:
    fn output() -> CastInfo {
        H::output() + V::output()
    }

    fn castable(value: &Value) -> bool {
        H::castable(value) || V::castable(value)
    }
}

impl<H, V> IntoValue for SpecificAlignment<H, V>
where
    H: Into<HAlignment> + Copy + Reflect,
    V: Into<VAlignment> + Copy + Reflect,
    HAlignment: Into<H>,
    VAlignment: Into<V>,
{
    fn into_value(self) -> Value {
        let alignment = match self {
            Self::H(x) => Alignment::H(x.into()),
            Self::V(y) => Alignment::V(y.into()),
            Self::Both(x, y) => Alignment::Both(x.into(), y.into()),
        };
        alignment.into_value()
    }
}

impl<H, V> FromValue for SpecificAlignment<H, V>
where
    H: Into<HAlignment> + Copy + Reflect + FromValue,
    V: Into<VAlignment> + Copy + Reflect + FromValue,
    HAlignment: Into<H>,
    VAlignment: Into<V>,
{
    fn from_value(value: Value) -> StrResult<Self> {
        if Alignment::castable(&value) {
            let align = Alignment::from_value(value)?;
            let result = match align {
                Alignment::H(x) => {
                    let h_value = x.into_value();
                    Self::H(H::from_value(h_value)?)
                }
                Alignment::V(y) => {
                    let v_value = y.into_value();
                    Self::V(V::from_value(v_value)?)
                }
                Alignment::Both(x, y) => {
                    let h_value = x.into_value();
                    let v_value = y.into_value();
                    Self::Both(H::from_value(h_value)?, V::from_value(v_value)?)
                }
            };

Review comment (suggestion):
No need to repeat the previous impl.

(If the Reflect bounds were really needed, feel free to add them back. But they don't seem to be at a first glance, unless Reflect is a supertrait of IntoValue, which it might very well be, and then you'd need to add the bounds back for the code to compile.)

```suggestion
impl<H, V> IntoValue for SpecificAlignment<H, V>
where
    HAlignment: From<H>,
    VAlignment: From<V>,
{
    fn into_value(self) -> Value {
       Alignment::from(self).into_value()
    }
}

```


Code after:
        H::output() + V::output()
    }

    fn castable(value: &Value) -> bool {
        H::castable(value) || V::castable(value)
    }
}

impl<H, V> IntoValue for SpecificAlignment<H, V>
where
    HAlignment: From<H>,
    VAlignment: From<V>,
{
    fn into_value(self) -> Value {
        Alignment::from(self).into_value()
    }
}

impl<H, V> FromValue for SpecificAlignment<H, V>
where
    H: Reflect + TryFrom<Alignment, Error = EcoString>,
    V: Reflect + TryFrom<Alignment, Error = EcoString>,
{
    fn from_value(value: Value) -> StrResult<Self> {
        if Alignment::castable(&value) {
            let align = Alignment::from_value(value)?;
            let result = match align {
                Alignment::H(_) => Self::H(H::try_from(align)?),
                Alignment::V(_) => Self::V(V::try_from(align)?),
                Alignment::Both(h, v) => {
                    Self::Both(H::try_from(h.into())?, V::try_from(v.into())?)
                }
            };
            return Ok(result);
        }
        Err(Self::error(&value))
    }
}

/// A fixed alignment in the global coordinate space.
///
/// For horizontal alignment, start is globally left and for vertical alignment
/// it is globally top.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum FixedAlignment {
    Start,
    Center,
    End,
}

impl FixedAlignment {