Skip to main content

style/values/generics/
calc.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5//! [Calc expressions][calc].
6//!
7//! [calc]: https://drafts.csswg.org/css-values/#calc-notation
8
9use crate::derives::*;
10use crate::typed_om::{MathSum, MathValue, NumericValue, ToTyped, TypedValue};
11use crate::values::generics::length::GenericAnchorSizeFunction;
12use crate::values::generics::position::{GenericAnchorFunction, GenericAnchorSide};
13use crate::values::generics::Optional;
14use num_traits::Zero;
15use smallvec::SmallVec;
16use std::convert::AsRef;
17use std::fmt::{self, Write};
18use std::ops::{Add, Mul, Neg, Rem, Sub};
19use std::{cmp, mem};
20use strum_macros::AsRefStr;
21use style_traits::{CssWriter, ToCss};
22
23use thin_vec::ThinVec;
24
25/// Whether we're a `min` or `max` function.
26#[derive(
27    Clone,
28    Copy,
29    Debug,
30    Deserialize,
31    MallocSizeOf,
32    PartialEq,
33    Serialize,
34    ToAnimatedZero,
35    ToResolvedValue,
36    ToShmem,
37)]
38#[repr(u8)]
39pub enum MinMaxOp {
40    /// `min()`
41    Min,
42    /// `max()`
43    Max,
44}
45
46/// Whether we're a `mod` or `rem` function.
47#[derive(
48    Clone,
49    Copy,
50    Debug,
51    Deserialize,
52    MallocSizeOf,
53    PartialEq,
54    Serialize,
55    ToAnimatedZero,
56    ToResolvedValue,
57    ToShmem,
58)]
59#[repr(u8)]
60pub enum ModRemOp {
61    /// `mod()`
62    Mod,
63    /// `rem()`
64    Rem,
65}
66
67impl ModRemOp {
68    fn apply(self, dividend: f32, divisor: f32) -> f32 {
69        // In mod(A, B) only, if B is infinite and A has opposite sign to B
70        // (including an oppositely-signed zero), the result is NaN.
71        // https://drafts.csswg.org/css-values/#round-infinities
72        if matches!(self, Self::Mod)
73            && divisor.is_infinite()
74            && dividend.is_sign_negative() != divisor.is_sign_negative()
75        {
76            return f32::NAN;
77        }
78
79        let (r, same_sign_as) = match self {
80            Self::Mod => (dividend - divisor * (dividend / divisor).floor(), divisor),
81            Self::Rem => (dividend - divisor * (dividend / divisor).trunc(), dividend),
82        };
83        if r == 0.0 && same_sign_as.is_sign_negative() {
84            -0.0
85        } else {
86            r
87        }
88    }
89}
90
91/// The strategy used in `round()`
92#[derive(
93    Clone,
94    Copy,
95    Debug,
96    Deserialize,
97    MallocSizeOf,
98    PartialEq,
99    Serialize,
100    ToAnimatedZero,
101    ToResolvedValue,
102    ToShmem,
103)]
104#[repr(u8)]
105pub enum RoundingStrategy {
106    /// `round(nearest, a, b)`
107    /// round a to the nearest multiple of b
108    Nearest,
109    /// `round(up, a, b)`
110    /// round a up to the nearest multiple of b
111    Up,
112    /// `round(down, a, b)`
113    /// round a down to the nearest multiple of b
114    Down,
115    /// `round(to-zero, a, b)`
116    /// round a to the nearest multiple of b that is towards zero
117    ToZero,
118}
119
120/// The clamping mode used in `progress()`
121#[derive(
122    Clone,
123    Copy,
124    Debug,
125    Deserialize,
126    MallocSizeOf,
127    Parse,
128    PartialEq,
129    Serialize,
130    ToAnimatedZero,
131    ToCss,
132    ToResolvedValue,
133    ToShmem,
134)]
135#[repr(u8)]
136pub enum ProgressClampingMode {
137    /// `progress(value, start, end)`
138    /// Progress result is clamped to the range [0, 1}.
139    #[css(skip)]
140    Clamp,
141    /// `progress(no-clamp value, start, end)`
142    /// Progress result can be any number.
143    NoClamp,
144}
145
146impl ProgressClampingMode {
147    fn evaluate(self, value: f32, start: f32, end: f32) -> f32 {
148        if start == end && self == Self::Clamp {
149            return 0.;
150        }
151        let progress = crate::values::normalize((value - start) / (end - start));
152        match self {
153            Self::Clamp => progress.max(0.).min(1.),
154            Self::NoClamp => progress,
155        }
156    }
157}
158
159/// This determines the order in which we serialize members of a calc() sum.
160///
161/// See https://drafts.csswg.org/css-values-4/#sort-a-calculations-children
162#[derive(
163    AsRefStr, Clone, Copy, Debug, Eq, Ord, Parse, PartialEq, PartialOrd, MallocSizeOf, ToShmem,
164)]
165#[strum(serialize_all = "lowercase")]
166#[allow(missing_docs)]
167pub enum SortKey {
168    #[strum(serialize = "")]
169    Number,
170    #[css(skip)]
171    #[strum(serialize = "%")]
172    Percentage,
173    Cap,
174    Ch,
175    Cqb,
176    Cqh,
177    Cqi,
178    Cqmax,
179    Cqmin,
180    Cqw,
181    Deg,
182    Dppx,
183    Dvb,
184    Dvh,
185    Dvi,
186    Dvmax,
187    Dvmin,
188    Dvw,
189    Em,
190    Ex,
191    Ic,
192    Lh,
193    Lvb,
194    Lvh,
195    Lvi,
196    Lvmax,
197    Lvmin,
198    Lvw,
199    Ms,
200    Px,
201    Rcap,
202    Rch,
203    Rem,
204    Rex,
205    Ric,
206    Rlh,
207    S, // Sec
208    Svb,
209    Svh,
210    Svi,
211    Svmax,
212    Svmin,
213    Svw,
214    Vb,
215    Vh,
216    Vi,
217    Vmax,
218    Vmin,
219    Vw,
220    #[css(skip)]
221    ColorComponent,
222    #[css(skip)]
223    Other,
224}
225
226/// Fallback type for anchor functions within `calc()`.
227/// Ideally, the fallback type is initial type of the property (e.g.
228/// `GenericInset` for `left`), but that causes circular reference.
229/// TODO(dshin, bug 2034100): Investigate ways to not require this.
230/// This handles the parsing of unitless zeros, as well as ensuring
231/// that e.g. `calc(anchor(--foo left, 1px) + 10%)` round trips
232/// (sorting aside), instead of becoming
233/// `calc(anchor(--foo left, calc(1px)) + 10%)`.
234#[repr(C)]
235#[derive(
236    Clone,
237    Debug,
238    Deserialize,
239    MallocSizeOf,
240    PartialEq,
241    Serialize,
242    ToAnimatedZero,
243    ToResolvedValue,
244    ToShmem,
245)]
246pub struct GenericAnchorFunctionFallback<L> {
247    /// Was this node parsed as a calc node?
248    #[animation(constant)]
249    is_calc_node: bool,
250    /// The parsed fallback value. Stored as a calc node to break
251    /// the circular reference.
252    pub node: GenericCalcNode<L>,
253}
254
255impl<L> GenericAnchorFunctionFallback<L> {
256    /// Create a new anchor function fallback value.
257    pub fn new(is_calc_node: bool, node: GenericCalcNode<L>) -> Self {
258        Self { is_calc_node, node }
259    }
260}
261
262impl<L: CalcNodeLeaf> ToCss for GenericAnchorFunctionFallback<L> {
263    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
264    where
265        W: Write,
266    {
267        self.node.to_css_impl(
268            dest,
269            if self.is_calc_node {
270                ArgumentLevel::CalculationRoot
271            } else {
272                ArgumentLevel::ArgumentRoot
273            },
274        )
275    }
276}
277
278/// `anchor()` function used in math functions.
279pub type GenericCalcAnchorFunction<L> =
280    GenericAnchorFunction<Box<GenericCalcNode<L>>, Box<GenericAnchorFunctionFallback<L>>>;
281/// `anchor-size()` function used in math functions.
282pub type GenericCalcAnchorSizeFunction<L> =
283    GenericAnchorSizeFunction<Box<GenericAnchorFunctionFallback<L>>>;
284
285/// A generic node in a calc expression.
286///
287/// FIXME: This would be much more elegant if we used `Self` in the types below,
288/// but we can't because of https://github.com/serde-rs/serde/issues/1565.
289///
290/// FIXME: The following annotations are to workaround an LLVM inlining bug, see
291/// bug 1631929.
292///
293/// cbindgen:destructor-attributes=MOZ_NEVER_INLINE
294/// cbindgen:copy-constructor-attributes=MOZ_NEVER_INLINE
295/// cbindgen:eq-attributes=MOZ_NEVER_INLINE
296#[repr(u8)]
297#[derive(
298    Clone,
299    Debug,
300    Deserialize,
301    MallocSizeOf,
302    PartialEq,
303    Serialize,
304    ToAnimatedZero,
305    ToResolvedValue,
306    ToShmem,
307)]
308pub enum GenericCalcNode<L> {
309    /// A leaf node.
310    Leaf(L),
311    /// A node that negates its child, e.g. Negate(1) == -1.
312    Negate(Box<Self>),
313    /// A node that inverts its child, e.g. Invert(10) == 1 / 10 == 0.1. The child must always
314    /// resolve to a number unit.
315    Invert(Box<Self>),
316    /// A sum node, representing `a + b + c` where a, b, and c are the
317    /// arguments.
318    Sum(crate::OwnedSlice<Self>),
319    /// A product node, representing `a * b * c` where a, b, and c are the
320    /// arguments.
321    Product(crate::OwnedSlice<Self>),
322    /// A `min` or `max` function.
323    MinMax(crate::OwnedSlice<Self>, MinMaxOp),
324    /// A `clamp()` function.
325    Clamp {
326        /// The minimum value.
327        min: Box<Self>,
328        /// The central value.
329        center: Box<Self>,
330        /// The maximum value.
331        max: Box<Self>,
332    },
333    /// A `round()` function.
334    Round {
335        /// The rounding strategy.
336        strategy: RoundingStrategy,
337        /// The value to round.
338        value: Box<Self>,
339        /// The step value.
340        step: Box<Self>,
341    },
342    /// A `mod()` or `rem()` function.
343    ModRem {
344        /// The dividend calculation.
345        dividend: Box<Self>,
346        /// The divisor calculation.
347        divisor: Box<Self>,
348        /// Is the function mod or rem?
349        op: ModRemOp,
350    },
351    /// A `sin()` function.
352    Sin(Box<Self>),
353    /// A `cos()` function.
354    Cos(Box<Self>),
355    /// A `tan()` function.
356    Tan(Box<Self>),
357    /// An `asin()` function.
358    Asin(Box<Self>),
359    /// An `acos()` function.
360    Acos(Box<Self>),
361    /// An `atan()` function.
362    Atan(Box<Self>),
363    /// An `atan2()` function.
364    Atan2(Box<Self>, Box<Self>),
365    /// A `pow()` function.
366    Pow(Box<Self>, Box<Self>),
367    /// A `sqrt()` function.
368    Sqrt(Box<Self>),
369    /// A `hypot()` function
370    Hypot(crate::OwnedSlice<Self>),
371    /// A `log()` function.
372    Log(Box<Self>, Optional<Box<Self>>),
373    /// An `exp()` function.
374    Exp(Box<Self>),
375    /// An `abs()` function.
376    Abs(Box<Self>),
377    /// A `sign()` function.
378    Sign(Box<Self>),
379    /// A `progress()` function.
380    Progress {
381        /// Clamping mode for the result.
382        clamping_mode: ProgressClampingMode,
383        /// The progress value calculation.
384        value: Box<Self>,
385        /// The progress start calculation.
386        start: Box<Self>,
387        /// The progress end calculation.
388        end: Box<Self>,
389    },
390    /// An `anchor()` function.
391    Anchor(Box<GenericCalcAnchorFunction<L>>),
392    /// An `anchor-size()` function.
393    AnchorSize(Box<GenericCalcAnchorSizeFunction<L>>),
394}
395
396pub use self::GenericCalcNode as CalcNode;
397
398bitflags! {
399    /// Expected units we allow parsing within a `calc()` expression.
400    ///
401    /// This is used as a hint for the parser to fast-reject invalid
402    /// expressions. Numbers are always allowed because they multiply other
403    /// units.
404    #[derive(Clone, Copy, PartialEq, Eq)]
405    pub struct CalcUnits: u8 {
406        /// <length>
407        const LENGTH = 1 << 0;
408        /// <percentage>
409        const PERCENTAGE = 1 << 1;
410        /// <angle>
411        const ANGLE = 1 << 2;
412        /// <time>
413        const TIME = 1 << 3;
414        /// <resolution>
415        const RESOLUTION = 1 << 4;
416        /// <length-percentage>
417        const LENGTH_PERCENTAGE = Self::LENGTH.bits() | Self::PERCENTAGE.bits();
418        // NOTE: When you add to this, make sure to make Atan2 deal with these.
419        /// Allow all units.
420        const ALL = Self::LENGTH.bits() | Self::PERCENTAGE.bits() | Self::ANGLE.bits() |
421            Self::TIME.bits() | Self::RESOLUTION.bits();
422    }
423}
424
425impl CalcUnits {
426    /// Returns whether the flags only represent a single unit. This will return true for 0, which
427    /// is a "number" this is also fine.
428    #[inline]
429    fn is_single_unit(&self) -> bool {
430        self.bits() == 0 || self.bits() & (self.bits() - 1) == 0
431    }
432
433    /// Returns true if this unit is allowed to be summed with the given unit, otherwise false.
434    #[inline]
435    fn can_sum_with(&self, other: Self) -> bool {
436        match *self {
437            Self::LENGTH => other.intersects(Self::LENGTH | Self::PERCENTAGE),
438            Self::PERCENTAGE => other.intersects(Self::LENGTH | Self::PERCENTAGE),
439            Self::LENGTH_PERCENTAGE => other.intersects(Self::LENGTH | Self::PERCENTAGE),
440            u => u.is_single_unit() && other == u,
441        }
442    }
443}
444
445/// For percentage resolution, sometimes we can't assume that the percentage basis is positive (so
446/// we don't know whether a percentage is larger than another).
447pub enum PositivePercentageBasis {
448    /// The percent basis is not known-positive, we can't compare percentages.
449    Unknown,
450    /// The percent basis is known-positive, we assume larger percentages are larger.
451    Yes,
452}
453
454macro_rules! compare_helpers {
455    () => {
456        /// Return whether a leaf is greater than another.
457        #[allow(unused)]
458        fn gt(&self, other: &Self, basis_positive: PositivePercentageBasis) -> bool {
459            self.compare(other, basis_positive) == Some(cmp::Ordering::Greater)
460        }
461
462        /// Return whether a leaf is less than another.
463        fn lt(&self, other: &Self, basis_positive: PositivePercentageBasis) -> bool {
464            self.compare(other, basis_positive) == Some(cmp::Ordering::Less)
465        }
466
467        /// Return whether a leaf is smaller or equal than another.
468        fn lte(&self, other: &Self, basis_positive: PositivePercentageBasis) -> bool {
469            match self.compare(other, basis_positive) {
470                Some(cmp::Ordering::Less) => true,
471                Some(cmp::Ordering::Equal) => true,
472                Some(cmp::Ordering::Greater) => false,
473                None => false,
474            }
475        }
476    };
477}
478
479/// A trait that represents all the stuff a valid leaf of a calc expression.
480pub trait CalcNodeLeaf: Clone + Sized + PartialEq + ToCss + ToTyped {
481    /// Returns the unit of the leaf.
482    fn unit(&self) -> CalcUnits;
483
484    /// Returns the unitless value of this leaf if one is available.
485    fn unitless_value(&self) -> Option<f32>;
486
487    /// Returns the angle value in radians if this leaf is an angle.
488    fn as_angle_radians(&self) -> Option<f32>;
489
490    /// Creates a new angle leaf from a value in radians.
491    fn new_angle_from_radians(radians: f32) -> Self;
492
493    /// Return true if the units of both leaves are equal. (NOTE: Does not take
494    /// the values into account)
495    fn is_same_unit_as(&self, other: &Self) -> bool {
496        std::mem::discriminant(self) == std::mem::discriminant(other)
497    }
498
499    /// Do a partial comparison of these values.
500    fn compare(
501        &self,
502        other: &Self,
503        base_is_positive: PositivePercentageBasis,
504    ) -> Option<cmp::Ordering>;
505    compare_helpers!();
506
507    /// Create a new leaf with a number value.
508    fn new_number(value: f32) -> Self;
509
510    /// Returns a float value if the leaf is a number.
511    fn as_number(&self) -> Option<f32>;
512
513    /// Returns a number or angle radians if the leaf is a number or angle.
514    fn as_number_or_angle_radians(&self) -> Option<f32> {
515        self.as_number().or_else(|| self.as_angle_radians())
516    }
517
518    /// Whether this value is known-negative.
519    fn is_negative(&self) -> Result<bool, ()> {
520        self.unitless_value()
521            .map(|v| Ok(v.is_sign_negative()))
522            .unwrap_or_else(|| Err(()))
523    }
524
525    /// Whether this value is infinite.
526    fn is_infinite(&self) -> Result<bool, ()> {
527        self.unitless_value()
528            .map(|v| Ok(v.is_infinite()))
529            .unwrap_or_else(|| Err(()))
530    }
531
532    /// Whether this value is zero.
533    fn is_zero(&self) -> Result<bool, ()> {
534        self.unitless_value()
535            .map(|v| Ok(v.is_zero()))
536            .unwrap_or_else(|| Err(()))
537    }
538
539    /// Whether this value is NaN.
540    fn is_nan(&self) -> Result<bool, ()> {
541        self.unitless_value()
542            .map(|v| Ok(v.is_nan()))
543            .unwrap_or_else(|| Err(()))
544    }
545
546    /// Tries to merge one leaf into another using the sum, that is, perform `x` + `y`.
547    fn try_sum_in_place(&mut self, other: &Self) -> Result<(), ()>;
548
549    /// Try to merge the right leaf into the left by using a multiplication. Return true if the
550    /// merge was successful, otherwise false.
551    fn try_product_in_place(&mut self, other: &mut Self) -> bool;
552
553    /// Tries a generic arithmetic operation.
554    fn try_op<O>(&self, other: &Self, op: O) -> Result<Self, ()>
555    where
556        O: Fn(f32, f32) -> f32;
557
558    /// Map the value of this node with the given operation.
559    fn map(&mut self, op: impl FnMut(f32) -> f32) -> Result<(), ()>;
560
561    /// Canonicalizes the expression if necessary.
562    fn simplify(&mut self) -> SimplificationResult;
563
564    /// Returns the sort key for simplification.
565    fn sort_key(&self) -> SortKey;
566
567    /// Create a new leaf containing the sign() result of the given leaf.
568    fn sign_from(leaf: &impl CalcNodeLeaf) -> Result<Self, ()> {
569        let Some(value) = leaf.unitless_value() else {
570            return Err(());
571        };
572
573        Ok(Self::new_number(if value.is_nan() {
574            f32::NAN
575        } else if value.is_zero() {
576            value
577        } else if value.is_sign_negative() {
578            -1.0
579        } else {
580            1.0
581        }))
582    }
583
584    /// Whether this leaf node should serialize with a `calc()` wrapper
585    /// if this node is the root of the calculation tree.
586    fn should_serialize_with_root_calc_wrapper(&self) -> bool {
587        true
588    }
589}
590
591/// The level of any argument being serialized in `to_css_impl`.
592#[derive(Clone)]
593enum ArgumentLevel {
594    /// The root of a calculation tree.
595    CalculationRoot,
596    /// The root of an operand node's argument, e.g. `min(10, 20)`, `10` and `20` will have this
597    /// level, but min in this case will have `TopMost`.
598    ArgumentRoot,
599    /// Any other values serialized in the tree.
600    Nested,
601}
602
603/// The result of simplify_and_sort_direct_children
604#[derive(Clone, Copy)]
605pub enum SimplificationResult {
606    /// This node (Or some of its descendants, if any) was simplified.
607    Simplified,
608    /// The children was unchanged.
609    Unchanged,
610}
611
612impl<L: CalcNodeLeaf> CalcNode<L> {
613    /// Create a dummy CalcNode that can be used to do replacements of other nodes.
614    fn dummy() -> Self {
615        Self::MinMax(Default::default(), MinMaxOp::Max)
616    }
617
618    /// Change all the leaf nodes to have the given value. This is useful when
619    /// you have `calc(1px * nan)` and you want to replace the product node with
620    /// `calc(nan)`, in which case the unit will be retained.
621    fn coerce_to_value(&mut self, value: f32) -> Result<(), ()> {
622        self.map(|_| value)
623    }
624
625    /// Return true if a product is distributive over this node.
626    /// Is distributive: (2 + 3) * 4 = 8 + 12
627    /// Not distributive: sign(2 + 3) * 4 != sign(8 + 12)
628    #[inline]
629    pub fn is_product_distributive(&self) -> bool {
630        match self {
631            // If there's no value, we can't distribute the product.
632            Self::Leaf(l) => l.unitless_value().is_some(),
633            Self::Sum(children) => children.iter().all(|c| c.is_product_distributive()),
634            _ => false,
635        }
636    }
637
638    /// If the node has a valid unit outcome, then return it, otherwise fail.
639    pub fn unit(&self) -> Result<CalcUnits, ()> {
640        Ok(match self {
641            CalcNode::Leaf(l) => l.unit(),
642            CalcNode::Negate(child) | CalcNode::Abs(child) => child.unit()?,
643            CalcNode::Sum(children) => {
644                let mut unit = children.first().unwrap().unit()?;
645                for child in children.iter().skip(1) {
646                    let child_unit = child.unit()?;
647                    if !child_unit.can_sum_with(unit) {
648                        return Err(());
649                    }
650                    unit |= child_unit;
651                }
652                unit
653            },
654            CalcNode::Product(children) => {
655                // Only one node is allowed to have a unit, the rest must be numbers.
656                let mut unit = None;
657                for child in children.iter() {
658                    let child_unit = child.unit()?;
659                    if child_unit.is_empty() {
660                        // Numbers are always allowed in a product, so continue with the next.
661                        continue;
662                    }
663
664                    if unit.is_some() {
665                        // We already have a unit for the node, so another unit node is invalid.
666                        return Err(());
667                    }
668
669                    // We have the unit for the node.
670                    unit = Some(child_unit);
671                }
672                // We only keep track of specified units, so if we end up with a None and no failure
673                // so far, then we have a number.
674                unit.unwrap_or(CalcUnits::empty())
675            },
676            CalcNode::MinMax(children, _) | CalcNode::Hypot(children) => {
677                let mut unit = children.first().unwrap().unit()?;
678                for child in children.iter().skip(1) {
679                    let child_unit = child.unit()?;
680                    if !child_unit.can_sum_with(unit) {
681                        return Err(());
682                    }
683                    unit |= child_unit;
684                }
685                unit
686            },
687            CalcNode::Clamp { min, center, max } => {
688                let min_unit = min.unit()?;
689                let center_unit = center.unit()?;
690
691                if !min_unit.can_sum_with(center_unit) {
692                    return Err(());
693                }
694
695                let max_unit = max.unit()?;
696
697                if !center_unit.can_sum_with(max_unit) {
698                    return Err(());
699                }
700
701                min_unit | center_unit | max_unit
702            },
703            CalcNode::Round { value, step, .. } => {
704                let value_unit = value.unit()?;
705                let step_unit = step.unit()?;
706                if !step_unit.can_sum_with(value_unit) {
707                    return Err(());
708                }
709                value_unit | step_unit
710            },
711            CalcNode::ModRem {
712                dividend, divisor, ..
713            } => {
714                let dividend_unit = dividend.unit()?;
715                let divisor_unit = divisor.unit()?;
716                if !divisor_unit.can_sum_with(dividend_unit) {
717                    return Err(());
718                }
719                dividend_unit | divisor_unit
720            },
721            CalcNode::Sign(ref child) => {
722                // sign() always resolves to a number, but we still need to make sure that the
723                // child units make sense.
724                let _ = child.unit()?;
725                CalcUnits::empty()
726            },
727            CalcNode::Anchor(..) | CalcNode::AnchorSize(..) => CalcUnits::LENGTH_PERCENTAGE,
728            CalcNode::Sin(ref child) | CalcNode::Cos(ref child) | CalcNode::Tan(ref child) => {
729                let child_unit = child.unit()?;
730                if !child_unit.is_empty() && !child_unit.intersects(CalcUnits::ANGLE) {
731                    return Err(());
732                }
733                CalcUnits::empty()
734            },
735            CalcNode::Asin(ref child) | CalcNode::Acos(ref child) | CalcNode::Atan(ref child) => {
736                let child_unit = child.unit()?;
737                if !child_unit.is_empty() {
738                    return Err(());
739                }
740                CalcUnits::ANGLE
741            },
742            CalcNode::Atan2(ref a, ref b) => {
743                let a_unit = a.unit()?;
744                let b_unit = b.unit()?;
745                if !a_unit.can_sum_with(b_unit) {
746                    return Err(());
747                }
748                CalcUnits::ANGLE
749            },
750            CalcNode::Pow(ref a, ref b) => {
751                let a_unit = a.unit()?;
752                let b_unit = b.unit()?;
753                if !a_unit.is_empty() || !b_unit.is_empty() {
754                    return Err(());
755                }
756                CalcUnits::empty()
757            },
758            CalcNode::Invert(ref c) | CalcNode::Sqrt(ref c) | CalcNode::Exp(ref c) => {
759                let child_unit = c.unit()?;
760                if !child_unit.is_empty() {
761                    return Err(());
762                }
763                CalcUnits::empty()
764            },
765            CalcNode::Log(ref a, ref b) => {
766                let a_unit = a.unit()?;
767                let b_unit = match b {
768                    Optional::Some(b) => b.unit()?,
769                    Optional::None => CalcUnits::empty(),
770                };
771                if !a_unit.is_empty() || !b_unit.is_empty() {
772                    return Err(());
773                }
774                CalcUnits::empty()
775            },
776            CalcNode::Progress {
777                value, start, end, ..
778            } => {
779                let value_unit = value.unit()?;
780                let start_unit = start.unit()?;
781                let end_unit = end.unit()?;
782                if !value_unit.can_sum_with(start_unit) || !value_unit.can_sum_with(end_unit) {
783                    return Err(());
784                }
785                CalcUnits::empty()
786            },
787        })
788    }
789
790    /// Negate the node inline.  If the node is distributive, it is replaced by the result,
791    /// otherwise the node is wrapped in a [`Negate`] node.
792    pub fn negate(&mut self) {
793        /// Node(params) -> Negate(Node(params))
794        fn wrap_self_in_negate<L: CalcNodeLeaf>(s: &mut CalcNode<L>) {
795            let result = mem::replace(s, CalcNode::dummy());
796            *s = CalcNode::Negate(Box::new(result));
797        }
798
799        match *self {
800            CalcNode::Leaf(ref mut leaf) => {
801                if leaf.map(std::ops::Neg::neg).is_err() {
802                    wrap_self_in_negate(self)
803                }
804            },
805            CalcNode::Negate(ref mut value) => {
806                // Don't negate the value here.  Replace `self` with it's child.
807                let result = mem::replace(value.as_mut(), Self::dummy());
808                *self = result;
809            },
810            CalcNode::Invert(_) => {
811                // -(1 / -10) == -(-0.1) == 0.1
812                wrap_self_in_negate(self)
813            },
814            CalcNode::Sum(ref mut children) => {
815                for child in children.iter_mut() {
816                    child.negate();
817                }
818            },
819            CalcNode::Product(_) => {
820                // -(2 * 3 / 4) == -(1.5)
821                wrap_self_in_negate(self);
822            },
823            CalcNode::MinMax(ref mut children, ref mut op) => {
824                for child in children.iter_mut() {
825                    child.negate();
826                }
827
828                // Negating min-max means the operation is swapped.
829                *op = match *op {
830                    MinMaxOp::Min => MinMaxOp::Max,
831                    MinMaxOp::Max => MinMaxOp::Min,
832                };
833            },
834            CalcNode::Clamp {
835                ref mut min,
836                ref mut center,
837                ref mut max,
838            } => {
839                if min.lte(max, PositivePercentageBasis::Unknown) {
840                    min.negate();
841                    center.negate();
842                    max.negate();
843
844                    mem::swap(min, max);
845                } else {
846                    wrap_self_in_negate(self);
847                }
848            },
849            CalcNode::Round {
850                ref mut strategy,
851                ref mut value,
852                ref mut step,
853            } => {
854                match *strategy {
855                    RoundingStrategy::Nearest => {
856                        // Nearest is tricky because we'd have to swap the
857                        // behavior at the half-way point from using the upper
858                        // to lower bound.
859                        // Simpler to just wrap self in a negate node.
860                        wrap_self_in_negate(self);
861                        return;
862                    },
863                    RoundingStrategy::Up => *strategy = RoundingStrategy::Down,
864                    RoundingStrategy::Down => *strategy = RoundingStrategy::Up,
865                    RoundingStrategy::ToZero => (),
866                }
867                value.negate();
868                step.negate();
869            },
870            CalcNode::ModRem {
871                ref mut dividend,
872                ref mut divisor,
873                ..
874            } => {
875                dividend.negate();
876                divisor.negate();
877            },
878            CalcNode::Hypot(ref mut children) => {
879                for child in children.iter_mut() {
880                    child.negate();
881                }
882            },
883            CalcNode::Sign(ref mut child) => {
884                child.negate();
885            },
886            CalcNode::Sin(..)
887            | CalcNode::Cos(..)
888            | CalcNode::Tan(..)
889            | CalcNode::Asin(..)
890            | CalcNode::Acos(..)
891            | CalcNode::Atan(..)
892            | CalcNode::Atan2(..)
893            | CalcNode::Pow(..)
894            | CalcNode::Sqrt(..)
895            | CalcNode::Log(..)
896            | CalcNode::Exp(..)
897            | CalcNode::Abs(..)
898            | CalcNode::Progress { .. }
899            | CalcNode::Anchor(..)
900            | CalcNode::AnchorSize(..) => {
901                wrap_self_in_negate(self);
902            },
903        }
904    }
905
906    fn sort_key(&self) -> SortKey {
907        match *self {
908            Self::Leaf(ref l) => l.sort_key(),
909            Self::Anchor(..) | Self::AnchorSize(..) => SortKey::Px,
910            _ => SortKey::Other,
911        }
912    }
913
914    /// Returns the leaf if we can (if simplification has allowed it).
915    pub fn as_leaf(&self) -> Option<&L> {
916        match *self {
917            Self::Leaf(ref l) => Some(l),
918            _ => None,
919        }
920    }
921
922    /// Tries to merge one node into another using the sum, that is, perform `x` + `y`.
923    pub fn try_sum_in_place(&mut self, other: &Self) -> Result<(), ()> {
924        match (self, other) {
925            (&mut CalcNode::Leaf(ref mut one), &CalcNode::Leaf(ref other)) => {
926                one.try_sum_in_place(other)
927            },
928            _ => Err(()),
929        }
930    }
931
932    /// Tries to merge one node into another using the product, that is, perform `x` * `y`.
933    pub fn try_product_in_place(&mut self, other: &mut Self) -> bool {
934        if let Ok(resolved) = other.resolve() {
935            if let Some(number) = resolved.as_number() {
936                if number == 1.0 {
937                    return true;
938                }
939
940                if self.is_product_distributive() {
941                    if self.map(|v| v * number).is_err() {
942                        return false;
943                    }
944                    return true;
945                }
946            }
947        }
948
949        if let Ok(resolved) = self.resolve() {
950            if let Some(number) = resolved.as_number() {
951                if number == 1.0 {
952                    std::mem::swap(self, other);
953                    return true;
954                }
955
956                if other.is_product_distributive() {
957                    if other.map(|v| v * number).is_err() {
958                        return false;
959                    }
960                    std::mem::swap(self, other);
961                    return true;
962                }
963            }
964        }
965
966        false
967    }
968
969    /// Tries to apply a generic arithmetic operator
970    fn try_op<O>(&self, other: &Self, op: O) -> Result<Self, ()>
971    where
972        O: Fn(f32, f32) -> f32,
973    {
974        match (self, other) {
975            (&CalcNode::Leaf(ref one), &CalcNode::Leaf(ref other)) => {
976                Ok(CalcNode::Leaf(one.try_op(other, op)?))
977            },
978            _ => Err(()),
979        }
980    }
981
982    /// Map the value of this node with the given operation.
983    pub fn map(&mut self, mut op: impl FnMut(f32) -> f32) -> Result<(), ()> {
984        fn map_internal<L: CalcNodeLeaf>(
985            node: &mut CalcNode<L>,
986            op: &mut impl FnMut(f32) -> f32,
987        ) -> Result<(), ()> {
988            match node {
989                CalcNode::Leaf(l) => l.map(op),
990                CalcNode::Negate(v) | CalcNode::Invert(v) => map_internal(v, op),
991                CalcNode::Sum(children) | CalcNode::Product(children) => {
992                    for node in &mut **children {
993                        map_internal(node, op)?;
994                    }
995                    Ok(())
996                },
997                CalcNode::MinMax(children, _) => {
998                    for node in &mut **children {
999                        map_internal(node, op)?;
1000                    }
1001                    Ok(())
1002                },
1003                CalcNode::Clamp { min, center, max } => {
1004                    map_internal(min, op)?;
1005                    map_internal(center, op)?;
1006                    map_internal(max, op)
1007                },
1008                CalcNode::Round { value, step, .. } => {
1009                    map_internal(value, op)?;
1010                    map_internal(step, op)
1011                },
1012                CalcNode::ModRem {
1013                    dividend, divisor, ..
1014                } => {
1015                    map_internal(dividend, op)?;
1016                    map_internal(divisor, op)
1017                },
1018                CalcNode::Hypot(children) => {
1019                    for node in &mut **children {
1020                        map_internal(node, op)?;
1021                    }
1022                    Ok(())
1023                },
1024                CalcNode::Abs(child) | CalcNode::Sign(child) => map_internal(child, op),
1025                // It is invalid to treat inner `CalcNode`s here - `anchor(--foo 50%) / 2` != `anchor(--foo 25%)`.
1026                // Same applies to fallback, as we don't know if it will be used. Similar reasoning applies to `anchor-size()`.
1027                CalcNode::Anchor(_) | CalcNode::AnchorSize(_) => Err(()),
1028                // Trig functions are nonlinear: 2 * sin(x) != sin(2*x).
1029                // Similarly for pow/sqrt/log/exp.
1030                CalcNode::Sin(_)
1031                | CalcNode::Cos(_)
1032                | CalcNode::Tan(_)
1033                | CalcNode::Asin(_)
1034                | CalcNode::Acos(_)
1035                | CalcNode::Atan(_)
1036                | CalcNode::Atan2(..)
1037                | CalcNode::Pow(..)
1038                | CalcNode::Sqrt(_)
1039                | CalcNode::Log(..)
1040                | CalcNode::Exp(_)
1041                | CalcNode::Progress { .. } => Err(()),
1042            }
1043        }
1044
1045        map_internal(self, &mut op)
1046    }
1047
1048    /// Convert this `CalcNode` into a `CalcNode` with a different leaf kind.
1049    pub fn map_leaves<O, F>(&self, mut map: F) -> CalcNode<O>
1050    where
1051        O: CalcNodeLeaf,
1052        F: FnMut(&L) -> O,
1053    {
1054        self.map_leaves_internal(&mut map)
1055    }
1056
1057    fn map_leaves_internal<O, F>(&self, map: &mut F) -> CalcNode<O>
1058    where
1059        O: CalcNodeLeaf,
1060        F: FnMut(&L) -> O,
1061    {
1062        fn map_children<L, O, F>(
1063            children: &[CalcNode<L>],
1064            map: &mut F,
1065        ) -> crate::OwnedSlice<CalcNode<O>>
1066        where
1067            L: CalcNodeLeaf,
1068            O: CalcNodeLeaf,
1069            F: FnMut(&L) -> O,
1070        {
1071            children
1072                .iter()
1073                .map(|c| c.map_leaves_internal(map))
1074                .collect()
1075        }
1076
1077        match *self {
1078            Self::Leaf(ref l) => CalcNode::Leaf(map(l)),
1079            Self::Negate(ref c) => CalcNode::Negate(Box::new(c.map_leaves_internal(map))),
1080            Self::Invert(ref c) => CalcNode::Invert(Box::new(c.map_leaves_internal(map))),
1081            Self::Sum(ref c) => CalcNode::Sum(map_children(c, map)),
1082            Self::Product(ref c) => CalcNode::Product(map_children(c, map)),
1083            Self::MinMax(ref c, op) => CalcNode::MinMax(map_children(c, map), op),
1084            Self::Clamp {
1085                ref min,
1086                ref center,
1087                ref max,
1088            } => {
1089                let min = Box::new(min.map_leaves_internal(map));
1090                let center = Box::new(center.map_leaves_internal(map));
1091                let max = Box::new(max.map_leaves_internal(map));
1092                CalcNode::Clamp { min, center, max }
1093            },
1094            Self::Round {
1095                strategy,
1096                ref value,
1097                ref step,
1098            } => {
1099                let value = Box::new(value.map_leaves_internal(map));
1100                let step = Box::new(step.map_leaves_internal(map));
1101                CalcNode::Round {
1102                    strategy,
1103                    value,
1104                    step,
1105                }
1106            },
1107            Self::ModRem {
1108                ref dividend,
1109                ref divisor,
1110                op,
1111            } => {
1112                let dividend = Box::new(dividend.map_leaves_internal(map));
1113                let divisor = Box::new(divisor.map_leaves_internal(map));
1114                CalcNode::ModRem {
1115                    dividend,
1116                    divisor,
1117                    op,
1118                }
1119            },
1120            Self::Sin(ref c) => CalcNode::Sin(Box::new(c.map_leaves_internal(map))),
1121            Self::Cos(ref c) => CalcNode::Cos(Box::new(c.map_leaves_internal(map))),
1122            Self::Tan(ref c) => CalcNode::Tan(Box::new(c.map_leaves_internal(map))),
1123            Self::Asin(ref c) => CalcNode::Asin(Box::new(c.map_leaves_internal(map))),
1124            Self::Acos(ref c) => CalcNode::Acos(Box::new(c.map_leaves_internal(map))),
1125            Self::Atan(ref c) => CalcNode::Atan(Box::new(c.map_leaves_internal(map))),
1126            Self::Atan2(ref a, ref b) => CalcNode::Atan2(
1127                Box::new(a.map_leaves_internal(map)),
1128                Box::new(b.map_leaves_internal(map)),
1129            ),
1130            Self::Pow(ref a, ref b) => CalcNode::Pow(
1131                Box::new(a.map_leaves_internal(map)),
1132                Box::new(b.map_leaves_internal(map)),
1133            ),
1134            Self::Sqrt(ref c) => CalcNode::Sqrt(Box::new(c.map_leaves_internal(map))),
1135            Self::Hypot(ref c) => CalcNode::Hypot(map_children(c, map)),
1136            Self::Log(ref a, ref b) => CalcNode::Log(
1137                Box::new(a.map_leaves_internal(map)),
1138                b.as_ref()
1139                    .map(|b| Box::new(b.map_leaves_internal(map)))
1140                    .into(),
1141            ),
1142            Self::Exp(ref c) => CalcNode::Exp(Box::new(c.map_leaves_internal(map))),
1143            Self::Abs(ref c) => CalcNode::Abs(Box::new(c.map_leaves_internal(map))),
1144            Self::Sign(ref c) => CalcNode::Sign(Box::new(c.map_leaves_internal(map))),
1145            Self::Progress {
1146                clamping_mode,
1147                ref value,
1148                ref start,
1149                ref end,
1150            } => {
1151                let value = Box::new(value.map_leaves_internal(map));
1152                let start = Box::new(start.map_leaves_internal(map));
1153                let end = Box::new(end.map_leaves_internal(map));
1154                CalcNode::Progress {
1155                    clamping_mode,
1156                    value,
1157                    start,
1158                    end,
1159                }
1160            },
1161            Self::Anchor(ref f) => CalcNode::Anchor(Box::new(GenericAnchorFunction {
1162                target_element: f.target_element.clone(),
1163                side: match &f.side {
1164                    GenericAnchorSide::Keyword(k) => GenericAnchorSide::Keyword(*k),
1165                    GenericAnchorSide::Percentage(p) => {
1166                        GenericAnchorSide::Percentage(Box::new(p.map_leaves_internal(map)))
1167                    },
1168                },
1169                fallback: f
1170                    .fallback
1171                    .as_ref()
1172                    .map(|fb| {
1173                        Box::new(GenericAnchorFunctionFallback::new(
1174                            fb.is_calc_node,
1175                            fb.node.map_leaves_internal(map),
1176                        ))
1177                    })
1178                    .into(),
1179            })),
1180            Self::AnchorSize(ref f) => CalcNode::AnchorSize(Box::new(GenericAnchorSizeFunction {
1181                target_element: f.target_element.clone(),
1182                size: f.size,
1183                fallback: f
1184                    .fallback
1185                    .as_ref()
1186                    .map(|fb| {
1187                        Box::new(GenericAnchorFunctionFallback::new(
1188                            fb.is_calc_node,
1189                            fb.node.map_leaves_internal(map),
1190                        ))
1191                    })
1192                    .into(),
1193            })),
1194        }
1195    }
1196
1197    /// Resolve this node into a value.
1198    pub fn resolve(&self) -> Result<L, ()> {
1199        self.resolve_map(|l| Ok(l.clone()))
1200    }
1201
1202    /// Resolve this node into a value, given a function that maps the leaf values.
1203    pub fn resolve_map<F>(&self, mut leaf_to_output_fn: F) -> Result<L, ()>
1204    where
1205        F: FnMut(&L) -> Result<L, ()>,
1206    {
1207        self.resolve_internal(&mut leaf_to_output_fn)
1208    }
1209
1210    fn resolve_internal<F>(&self, leaf_to_output_fn: &mut F) -> Result<L, ()>
1211    where
1212        F: FnMut(&L) -> Result<L, ()>,
1213    {
1214        match self {
1215            Self::Leaf(l) => leaf_to_output_fn(l),
1216            Self::Negate(child) => {
1217                let mut result = child.resolve_internal(leaf_to_output_fn)?;
1218                result.map(|v| v.neg())?;
1219                Ok(result)
1220            },
1221            Self::Invert(child) => {
1222                let mut result = child.resolve_internal(leaf_to_output_fn)?;
1223                result.map(|v| 1.0 / v)?;
1224                Ok(result)
1225            },
1226            Self::Sum(children) => {
1227                let mut result = children[0].resolve_internal(leaf_to_output_fn)?;
1228
1229                for child in children.iter().skip(1) {
1230                    let right = child.resolve_internal(leaf_to_output_fn)?;
1231                    // try_op will make sure we only sum leaves with the same type.
1232                    result = result.try_op(&right, |left, right| left + right)?;
1233                }
1234
1235                Ok(result)
1236            },
1237            Self::Product(children) => {
1238                let mut result = children[0].resolve_internal(leaf_to_output_fn)?;
1239
1240                for child in children.iter().skip(1) {
1241                    let right = child.resolve_internal(leaf_to_output_fn)?;
1242                    // Mutliply only allowed when either side is a number.
1243                    match result.as_number() {
1244                        Some(left) => {
1245                            // Left side is a number, so we use the right node as the result.
1246                            result = right;
1247                            result.map(|v| v * left)?;
1248                        },
1249                        None => {
1250                            // Left side is not a number, so check if the right side is.
1251                            match right.as_number() {
1252                                Some(right) => {
1253                                    result.map(|v| v * right)?;
1254                                },
1255                                None => {
1256                                    // Multiplying with both sides having units.
1257                                    return Err(());
1258                                },
1259                            }
1260                        },
1261                    }
1262                }
1263
1264                Ok(result)
1265            },
1266            Self::MinMax(children, op) => {
1267                let mut result = children[0].resolve_internal(leaf_to_output_fn)?;
1268
1269                if result.is_nan()? {
1270                    return Ok(result);
1271                }
1272
1273                for child in children.iter().skip(1) {
1274                    let candidate = child.resolve_internal(leaf_to_output_fn)?;
1275
1276                    // Leaf types must match for each child.
1277                    if !result.is_same_unit_as(&candidate) {
1278                        return Err(());
1279                    }
1280
1281                    if candidate.is_nan()? {
1282                        result = candidate;
1283                        break;
1284                    }
1285
1286                    let candidate_wins = match op {
1287                        MinMaxOp::Min => candidate.lt(&result, PositivePercentageBasis::Yes),
1288                        MinMaxOp::Max => candidate.gt(&result, PositivePercentageBasis::Yes),
1289                    };
1290
1291                    if candidate_wins {
1292                        result = candidate;
1293                    }
1294                }
1295
1296                Ok(result)
1297            },
1298            Self::Clamp { min, center, max } => {
1299                let min = min.resolve_internal(leaf_to_output_fn)?;
1300                let center = center.resolve_internal(leaf_to_output_fn)?;
1301                let max = max.resolve_internal(leaf_to_output_fn)?;
1302
1303                if !min.is_same_unit_as(&center) || !max.is_same_unit_as(&center) {
1304                    return Err(());
1305                }
1306
1307                if min.is_nan()? {
1308                    return Ok(min);
1309                }
1310
1311                if center.is_nan()? {
1312                    return Ok(center);
1313                }
1314
1315                if max.is_nan()? {
1316                    return Ok(max);
1317                }
1318
1319                let mut result = center;
1320                if result.gt(&max, PositivePercentageBasis::Yes) {
1321                    result = max;
1322                }
1323                if result.lt(&min, PositivePercentageBasis::Yes) {
1324                    result = min
1325                }
1326
1327                Ok(result)
1328            },
1329            Self::Round {
1330                strategy,
1331                value,
1332                step,
1333            } => {
1334                let mut value = value.resolve_internal(leaf_to_output_fn)?;
1335                let step = step.resolve_internal(leaf_to_output_fn)?;
1336
1337                if !value.is_same_unit_as(&step) {
1338                    return Err(());
1339                }
1340
1341                let Some(step) = step.unitless_value() else {
1342                    return Err(());
1343                };
1344                let step = step.abs();
1345
1346                value.map(|value| {
1347                    // TODO(emilio): Seems like at least a few of these
1348                    // special-cases could be removed if we do the math in a
1349                    // particular order.
1350                    if step.is_zero() {
1351                        return f32::NAN;
1352                    }
1353
1354                    if value.is_infinite() {
1355                        if step.is_infinite() {
1356                            return f32::NAN;
1357                        }
1358                        return value;
1359                    }
1360
1361                    if step.is_infinite() {
1362                        match strategy {
1363                            RoundingStrategy::Nearest | RoundingStrategy::ToZero => {
1364                                return if value.is_sign_negative() { -0.0 } else { 0.0 }
1365                            },
1366                            RoundingStrategy::Up => {
1367                                return if !value.is_sign_negative() && !value.is_zero() {
1368                                    f32::INFINITY
1369                                } else if !value.is_sign_negative() && value.is_zero() {
1370                                    value
1371                                } else {
1372                                    -0.0
1373                                }
1374                            },
1375                            RoundingStrategy::Down => {
1376                                return if value.is_sign_negative() && !value.is_zero() {
1377                                    -f32::INFINITY
1378                                } else if value.is_sign_negative() && value.is_zero() {
1379                                    value
1380                                } else {
1381                                    0.0
1382                                }
1383                            },
1384                        }
1385                    }
1386
1387                    let div = value / step;
1388                    let lower_bound = div.floor() * step;
1389                    let upper_bound = div.ceil() * step;
1390
1391                    match strategy {
1392                        RoundingStrategy::Nearest => {
1393                            // In case of a tie, use the upper bound
1394                            if value - lower_bound < upper_bound - value {
1395                                lower_bound
1396                            } else {
1397                                upper_bound
1398                            }
1399                        },
1400                        RoundingStrategy::Up => upper_bound,
1401                        RoundingStrategy::Down => lower_bound,
1402                        RoundingStrategy::ToZero => {
1403                            // In case of a tie, use the upper bound
1404                            if lower_bound.abs() < upper_bound.abs() {
1405                                lower_bound
1406                            } else {
1407                                upper_bound
1408                            }
1409                        },
1410                    }
1411                })?;
1412
1413                Ok(value)
1414            },
1415            Self::ModRem {
1416                dividend,
1417                divisor,
1418                op,
1419            } => {
1420                let mut dividend = dividend.resolve_internal(leaf_to_output_fn)?;
1421                let divisor = divisor.resolve_internal(leaf_to_output_fn)?;
1422
1423                if !dividend.is_same_unit_as(&divisor) {
1424                    return Err(());
1425                }
1426
1427                let Some(divisor) = divisor.unitless_value() else {
1428                    return Err(());
1429                };
1430                dividend.map(|dividend| op.apply(dividend, divisor))?;
1431                Ok(dividend)
1432            },
1433            Self::Sin(ref c) => {
1434                let result = c.resolve_internal(leaf_to_output_fn)?;
1435                let radians = result.as_number_or_angle_radians().ok_or(())?;
1436                Ok(L::new_number(radians.sin()))
1437            },
1438            Self::Cos(ref c) => {
1439                let result = c.resolve_internal(leaf_to_output_fn)?;
1440                let radians = result.as_number_or_angle_radians().ok_or(())?;
1441                Ok(L::new_number(radians.cos()))
1442            },
1443            Self::Tan(ref c) => {
1444                let result = c.resolve_internal(leaf_to_output_fn)?;
1445                let radians = result.as_number_or_angle_radians().ok_or(())?;
1446                Ok(L::new_number(radians.tan()))
1447            },
1448            Self::Asin(ref c) => {
1449                let result = c.resolve_internal(leaf_to_output_fn)?;
1450                let value = result.as_number().ok_or(())?;
1451                Ok(L::new_angle_from_radians(value.asin()))
1452            },
1453            Self::Acos(ref c) => {
1454                let result = c.resolve_internal(leaf_to_output_fn)?;
1455                let value = result.as_number().ok_or(())?;
1456                Ok(L::new_angle_from_radians(value.acos()))
1457            },
1458            Self::Atan(ref c) => {
1459                let result = c.resolve_internal(leaf_to_output_fn)?;
1460                let value = result.as_number().ok_or(())?;
1461                Ok(L::new_angle_from_radians(value.atan()))
1462            },
1463            Self::Atan2(ref a, ref b) => {
1464                let a = a.resolve_internal(leaf_to_output_fn)?;
1465                let b = b.resolve_internal(leaf_to_output_fn)?;
1466                if !a.is_same_unit_as(&b) {
1467                    return Err(());
1468                }
1469                let a_val = a.unitless_value().ok_or(())?;
1470                let b_val = b.unitless_value().ok_or(())?;
1471                Ok(L::new_angle_from_radians(a_val.atan2(b_val)))
1472            },
1473            Self::Pow(ref a, ref b) => {
1474                let a = a.resolve_internal(leaf_to_output_fn)?;
1475                let b = b.resolve_internal(leaf_to_output_fn)?;
1476                let a_val = a.as_number().ok_or(())?;
1477                let b_val = b.as_number().ok_or(())?;
1478                Ok(L::new_number(a_val.powf(b_val)))
1479            },
1480            Self::Sqrt(ref c) => {
1481                let result = c.resolve_internal(leaf_to_output_fn)?;
1482                let value = result.as_number().ok_or(())?;
1483                Ok(L::new_number(value.sqrt()))
1484            },
1485            Self::Hypot(children) => {
1486                let mut result = children[0].resolve_internal(leaf_to_output_fn)?;
1487                result.map(|v| v.powi(2))?;
1488
1489                for child in children.iter().skip(1) {
1490                    let child_value = child.resolve_internal(leaf_to_output_fn)?;
1491
1492                    if !result.is_same_unit_as(&child_value) {
1493                        return Err(());
1494                    }
1495
1496                    let Some(child_value) = child_value.unitless_value() else {
1497                        return Err(());
1498                    };
1499                    result.map(|v| v + child_value.powi(2))?;
1500                }
1501
1502                result.map(|v| v.sqrt())?;
1503                Ok(result)
1504            },
1505            Self::Log(ref a, ref b) => {
1506                let a = a.resolve_internal(leaf_to_output_fn)?;
1507                let a_val = a.as_number().ok_or(())?;
1508                let result = match b {
1509                    Optional::Some(ref b) => {
1510                        let b = b.resolve_internal(leaf_to_output_fn)?;
1511                        let b_val = b.as_number().ok_or(())?;
1512                        a_val.log(b_val)
1513                    },
1514                    Optional::None => a_val.ln(),
1515                };
1516                Ok(L::new_number(result))
1517            },
1518            Self::Exp(ref c) => {
1519                let result = c.resolve_internal(leaf_to_output_fn)?;
1520                let value = result.as_number().ok_or(())?;
1521                Ok(L::new_number(value.exp()))
1522            },
1523            Self::Abs(ref c) => {
1524                let mut result = c.resolve_internal(leaf_to_output_fn)?;
1525
1526                result.map(|v| v.abs())?;
1527
1528                Ok(result)
1529            },
1530            Self::Sign(ref c) => {
1531                let result = c.resolve_internal(leaf_to_output_fn)?;
1532                Ok(L::sign_from(&result)?)
1533            },
1534            Self::Progress {
1535                clamping_mode,
1536                ref value,
1537                ref start,
1538                ref end,
1539            } => {
1540                let value = value.resolve_internal(leaf_to_output_fn)?;
1541                let start = start.resolve_internal(leaf_to_output_fn)?;
1542                let end = end.resolve_internal(leaf_to_output_fn)?;
1543                if !value.is_same_unit_as(&start) || !value.is_same_unit_as(&end) {
1544                    return Err(());
1545                }
1546
1547                let value = value.unitless_value().ok_or(())?;
1548                let start = start.unitless_value().ok_or(())?;
1549                let end = end.unitless_value().ok_or(())?;
1550                Ok(L::new_number(clamping_mode.evaluate(value, start, end)))
1551            },
1552            Self::Anchor(_) | Self::AnchorSize(_) => Err(()),
1553        }
1554    }
1555
1556    /// Mutate nodes within this calc node tree using given the mapping function.
1557    pub fn map_node<F>(&mut self, mut mapping_fn: F) -> Result<(), ()>
1558    where
1559        F: FnMut(&CalcNode<L>) -> Result<Option<CalcNode<L>>, ()>,
1560    {
1561        self.map_node_internal(&mut mapping_fn)
1562    }
1563
1564    fn map_node_internal<F>(&mut self, mapping_fn: &mut F) -> Result<(), ()>
1565    where
1566        F: FnMut(&CalcNode<L>) -> Result<Option<CalcNode<L>>, ()>,
1567    {
1568        if let Some(node) = mapping_fn(self)? {
1569            *self = node;
1570            // Assume that any sub-nodes don't need to be mutated.
1571            return Ok(());
1572        }
1573        match self {
1574            Self::Leaf(_) | Self::Anchor(_) | Self::AnchorSize(_) => (),
1575            Self::Negate(child)
1576            | Self::Invert(child)
1577            | Self::Abs(child)
1578            | Self::Sign(child)
1579            | Self::Sin(child)
1580            | Self::Cos(child)
1581            | Self::Tan(child)
1582            | Self::Asin(child)
1583            | Self::Acos(child)
1584            | Self::Atan(child)
1585            | Self::Sqrt(child)
1586            | Self::Exp(child) => {
1587                child.map_node_internal(mapping_fn)?;
1588            },
1589            Self::Atan2(a, b) => {
1590                a.map_node_internal(mapping_fn)?;
1591                b.map_node_internal(mapping_fn)?;
1592            },
1593            Self::Pow(a, b) => {
1594                a.map_node_internal(mapping_fn)?;
1595                b.map_node_internal(mapping_fn)?;
1596            },
1597            Self::Log(a, b) => {
1598                a.map_node_internal(mapping_fn)?;
1599                if let Optional::Some(b) = b {
1600                    b.map_node_internal(mapping_fn)?;
1601                }
1602            },
1603            Self::Sum(children)
1604            | Self::Product(children)
1605            | Self::Hypot(children)
1606            | Self::MinMax(children, _) => {
1607                for child in children.iter_mut() {
1608                    child.map_node_internal(mapping_fn)?;
1609                }
1610            },
1611            Self::Clamp { min, center, max } => {
1612                min.map_node_internal(mapping_fn)?;
1613                center.map_node_internal(mapping_fn)?;
1614                max.map_node_internal(mapping_fn)?;
1615            },
1616            Self::Round { value, step, .. } => {
1617                value.map_node_internal(mapping_fn)?;
1618                step.map_node_internal(mapping_fn)?;
1619            },
1620            Self::ModRem {
1621                dividend, divisor, ..
1622            } => {
1623                dividend.map_node_internal(mapping_fn)?;
1624                divisor.map_node_internal(mapping_fn)?;
1625            },
1626            Self::Progress {
1627                value, start, end, ..
1628            } => {
1629                value.map_node_internal(mapping_fn)?;
1630                start.map_node_internal(mapping_fn)?;
1631                end.map_node_internal(mapping_fn)?;
1632            },
1633        };
1634        Ok(())
1635    }
1636
1637    fn is_negative_leaf(&self) -> Result<bool, ()> {
1638        Ok(match *self {
1639            Self::Leaf(ref l) => l.is_negative()?,
1640            _ => false,
1641        })
1642    }
1643
1644    fn is_zero_leaf(&self) -> Result<bool, ()> {
1645        Ok(match *self {
1646            Self::Leaf(ref l) => l.is_zero()?,
1647            _ => false,
1648        })
1649    }
1650
1651    fn is_infinite_leaf(&self) -> Result<bool, ()> {
1652        Ok(match *self {
1653            Self::Leaf(ref l) => l.is_infinite()?,
1654            _ => false,
1655        })
1656    }
1657
1658    fn is_nan_leaf(&self) -> Result<bool, ()> {
1659        Ok(match *self {
1660            Self::Leaf(ref l) => l.is_nan()?,
1661            _ => false,
1662        })
1663    }
1664
1665    /// Visits all the nodes in this calculation tree recursively, starting by
1666    /// the leaves and bubbling all the way up.
1667    ///
1668    /// This is useful for simplification, but can also be used for validation
1669    /// and such.
1670    pub fn visit_depth_first(&mut self, mut f: impl FnMut(&mut Self)) {
1671        self.visit_depth_first_internal(&mut f)
1672    }
1673
1674    fn visit_depth_first_internal(&mut self, f: &mut impl FnMut(&mut Self)) {
1675        match *self {
1676            Self::Clamp {
1677                ref mut min,
1678                ref mut center,
1679                ref mut max,
1680            } => {
1681                min.visit_depth_first_internal(f);
1682                center.visit_depth_first_internal(f);
1683                max.visit_depth_first_internal(f);
1684            },
1685            Self::Round {
1686                ref mut value,
1687                ref mut step,
1688                ..
1689            } => {
1690                value.visit_depth_first_internal(f);
1691                step.visit_depth_first_internal(f);
1692            },
1693            Self::ModRem {
1694                ref mut dividend,
1695                ref mut divisor,
1696                ..
1697            } => {
1698                dividend.visit_depth_first_internal(f);
1699                divisor.visit_depth_first_internal(f);
1700            },
1701            Self::Sum(ref mut children)
1702            | Self::Product(ref mut children)
1703            | Self::MinMax(ref mut children, _)
1704            | Self::Hypot(ref mut children) => {
1705                for child in &mut **children {
1706                    child.visit_depth_first_internal(f);
1707                }
1708            },
1709            Self::Negate(ref mut value) | Self::Invert(ref mut value) => {
1710                value.visit_depth_first_internal(f);
1711            },
1712            Self::Sin(ref mut value)
1713            | Self::Cos(ref mut value)
1714            | Self::Tan(ref mut value)
1715            | Self::Asin(ref mut value)
1716            | Self::Acos(ref mut value)
1717            | Self::Atan(ref mut value)
1718            | Self::Sqrt(ref mut value)
1719            | Self::Exp(ref mut value) => {
1720                value.visit_depth_first_internal(f);
1721            },
1722            Self::Atan2(ref mut a, ref mut b) => {
1723                a.visit_depth_first_internal(f);
1724                b.visit_depth_first_internal(f);
1725            },
1726            Self::Pow(ref mut a, ref mut b) => {
1727                a.visit_depth_first_internal(f);
1728                b.visit_depth_first_internal(f);
1729            },
1730            Self::Log(ref mut a, ref mut b) => {
1731                a.visit_depth_first_internal(f);
1732                if let Optional::Some(b) = b {
1733                    b.visit_depth_first_internal(f);
1734                }
1735            },
1736            Self::Abs(ref mut value) | Self::Sign(ref mut value) => {
1737                value.visit_depth_first_internal(f);
1738            },
1739            Self::Progress {
1740                ref mut value,
1741                ref mut start,
1742                ref mut end,
1743                ..
1744            } => {
1745                value.visit_depth_first_internal(f);
1746                start.visit_depth_first_internal(f);
1747                end.visit_depth_first_internal(f);
1748            },
1749            Self::Leaf(..) | Self::Anchor(..) | Self::AnchorSize(..) => {},
1750        }
1751        f(self);
1752    }
1753
1754    /// This function simplifies and sorts the calculation of the specified node. It simplifies
1755    /// directly nested nodes while assuming that all nodes below it have already been simplified.
1756    /// It is recommended to use this function in combination with `visit_depth_first()`.
1757    ///
1758    /// This function is necessary only if the node needs to be preserved after parsing,
1759    /// specifically for `<length-percentage>` cases where the calculation contains percentages or
1760    /// relative units. Otherwise, the node can be evaluated using `resolve()`, which will
1761    /// automatically provide a simplified value.
1762    ///
1763    /// <https://drafts.csswg.org/css-values-4/#calc-simplification>
1764    pub fn simplify_and_sort_direct_children(&mut self) -> SimplificationResult {
1765        macro_rules! replace_self_with {
1766            ($slot:expr) => {{
1767                let result = mem::replace($slot, Self::dummy());
1768                *self = result;
1769            }};
1770        }
1771
1772        macro_rules! value_or_stop {
1773            ($op:expr) => {{
1774                match $op {
1775                    Ok(value) => value,
1776                    Err(_) => return SimplificationResult::Unchanged,
1777                }
1778            }};
1779        }
1780
1781        match *self {
1782            Self::Clamp {
1783                ref mut min,
1784                ref mut center,
1785                ref mut max,
1786            } => {
1787                // NOTE: clamp() is max(min, min(center, max))
1788                let min_cmp_center = match min.compare(&center, PositivePercentageBasis::Unknown) {
1789                    Some(o) => o,
1790                    None => return SimplificationResult::Unchanged,
1791                };
1792
1793                // So if we can prove that min is more than center, then we won,
1794                // as that's what we should always return.
1795                if matches!(min_cmp_center, cmp::Ordering::Greater) {
1796                    replace_self_with!(&mut **min);
1797                    return SimplificationResult::Simplified;
1798                }
1799
1800                // Otherwise try with max.
1801                let max_cmp_center = match max.compare(&center, PositivePercentageBasis::Unknown) {
1802                    Some(o) => o,
1803                    None => return SimplificationResult::Unchanged,
1804                };
1805
1806                if matches!(max_cmp_center, cmp::Ordering::Less) {
1807                    // max is less than center, so we need to return effectively
1808                    // `max(min, max)`.
1809                    let max_cmp_min = match max.compare(&min, PositivePercentageBasis::Unknown) {
1810                        Some(o) => o,
1811                        None => return SimplificationResult::Unchanged,
1812                    };
1813
1814                    if matches!(max_cmp_min, cmp::Ordering::Less) {
1815                        replace_self_with!(&mut **min);
1816                        return SimplificationResult::Simplified;
1817                    }
1818
1819                    replace_self_with!(&mut **max);
1820                    return SimplificationResult::Simplified;
1821                }
1822
1823                // Otherwise we're the center node.
1824                replace_self_with!(&mut **center);
1825                return SimplificationResult::Simplified;
1826            },
1827            Self::Round {
1828                strategy,
1829                ref mut value,
1830                ref mut step,
1831            } => {
1832                if value_or_stop!(step.is_zero_leaf()) {
1833                    value_or_stop!(value.coerce_to_value(f32::NAN));
1834                    replace_self_with!(&mut **value);
1835                    return SimplificationResult::Simplified;
1836                }
1837
1838                if value_or_stop!(value.is_infinite_leaf())
1839                    && value_or_stop!(step.is_infinite_leaf())
1840                {
1841                    value_or_stop!(value.coerce_to_value(f32::NAN));
1842                    replace_self_with!(&mut **value);
1843                    return SimplificationResult::Simplified;
1844                }
1845
1846                if value_or_stop!(value.is_infinite_leaf()) {
1847                    replace_self_with!(&mut **value);
1848                    return SimplificationResult::Simplified;
1849                }
1850
1851                if value_or_stop!(step.is_infinite_leaf()) {
1852                    match strategy {
1853                        RoundingStrategy::Nearest | RoundingStrategy::ToZero => {
1854                            value_or_stop!(value.coerce_to_value(0.0));
1855                            replace_self_with!(&mut **value);
1856                            return SimplificationResult::Simplified;
1857                        },
1858                        RoundingStrategy::Up => {
1859                            if !value_or_stop!(value.is_negative_leaf())
1860                                && !value_or_stop!(value.is_zero_leaf())
1861                            {
1862                                value_or_stop!(value.coerce_to_value(f32::INFINITY));
1863                                replace_self_with!(&mut **value);
1864                                return SimplificationResult::Simplified;
1865                            } else if !value_or_stop!(value.is_negative_leaf())
1866                                && value_or_stop!(value.is_zero_leaf())
1867                            {
1868                                replace_self_with!(&mut **value);
1869                                return SimplificationResult::Simplified;
1870                            } else {
1871                                value_or_stop!(value.coerce_to_value(0.0));
1872                                replace_self_with!(&mut **value);
1873                                return SimplificationResult::Simplified;
1874                            }
1875                        },
1876                        RoundingStrategy::Down => {
1877                            if value_or_stop!(value.is_negative_leaf())
1878                                && !value_or_stop!(value.is_zero_leaf())
1879                            {
1880                                value_or_stop!(value.coerce_to_value(-f32::INFINITY));
1881                                replace_self_with!(&mut **value);
1882                                return SimplificationResult::Simplified;
1883                            } else if value_or_stop!(value.is_negative_leaf())
1884                                && value_or_stop!(value.is_zero_leaf())
1885                            {
1886                                replace_self_with!(&mut **value);
1887                                return SimplificationResult::Simplified;
1888                            } else {
1889                                value_or_stop!(value.coerce_to_value(0.0));
1890                                replace_self_with!(&mut **value);
1891                                return SimplificationResult::Simplified;
1892                            }
1893                        },
1894                    }
1895                }
1896
1897                if value_or_stop!(step.is_negative_leaf()) {
1898                    step.negate();
1899                }
1900
1901                let remainder = value_or_stop!(value.try_op(step, Rem::rem));
1902                if value_or_stop!(remainder.is_zero_leaf()) {
1903                    replace_self_with!(&mut **value);
1904                    return SimplificationResult::Simplified;
1905                }
1906
1907                let (mut lower_bound, mut upper_bound) = if value_or_stop!(value.is_negative_leaf())
1908                {
1909                    let upper_bound = value_or_stop!(value.try_op(&remainder, Sub::sub));
1910                    let lower_bound = value_or_stop!(upper_bound.try_op(&step, Sub::sub));
1911
1912                    (lower_bound, upper_bound)
1913                } else {
1914                    let lower_bound = value_or_stop!(value.try_op(&remainder, Sub::sub));
1915                    let upper_bound = value_or_stop!(lower_bound.try_op(&step, Add::add));
1916
1917                    (lower_bound, upper_bound)
1918                };
1919
1920                match strategy {
1921                    RoundingStrategy::Nearest => {
1922                        let lower_diff = value_or_stop!(value.try_op(&lower_bound, Sub::sub));
1923                        let upper_diff = value_or_stop!(upper_bound.try_op(value, Sub::sub));
1924                        // In case of a tie, use the upper bound
1925                        if lower_diff.lt(&upper_diff, PositivePercentageBasis::Unknown) {
1926                            replace_self_with!(&mut lower_bound);
1927                        } else {
1928                            replace_self_with!(&mut upper_bound);
1929                        }
1930                    },
1931                    RoundingStrategy::Up => {
1932                        replace_self_with!(&mut upper_bound);
1933                    },
1934                    RoundingStrategy::Down => {
1935                        replace_self_with!(&mut lower_bound);
1936                    },
1937                    RoundingStrategy::ToZero => {
1938                        let mut lower_diff = lower_bound.clone();
1939                        let mut upper_diff = upper_bound.clone();
1940
1941                        if value_or_stop!(lower_diff.is_negative_leaf()) {
1942                            lower_diff.negate();
1943                        }
1944
1945                        if value_or_stop!(upper_diff.is_negative_leaf()) {
1946                            upper_diff.negate();
1947                        }
1948
1949                        // In case of a tie, use the upper bound
1950                        if lower_diff.lt(&upper_diff, PositivePercentageBasis::Unknown) {
1951                            replace_self_with!(&mut lower_bound);
1952                        } else {
1953                            replace_self_with!(&mut upper_bound);
1954                        }
1955                    },
1956                };
1957                return SimplificationResult::Simplified;
1958            },
1959            Self::ModRem {
1960                ref dividend,
1961                ref divisor,
1962                op,
1963            } => {
1964                let mut result = value_or_stop!(dividend.try_op(divisor, |a, b| op.apply(a, b)));
1965                replace_self_with!(&mut result);
1966                return SimplificationResult::Simplified;
1967            },
1968            Self::MinMax(ref mut children, op) => {
1969                let winning_order = match op {
1970                    MinMaxOp::Min => cmp::Ordering::Less,
1971                    MinMaxOp::Max => cmp::Ordering::Greater,
1972                };
1973
1974                if value_or_stop!(children[0].is_nan_leaf()) {
1975                    replace_self_with!(&mut children[0]);
1976                    return SimplificationResult::Simplified;
1977                }
1978
1979                let mut result = 0;
1980                for i in 1..children.len() {
1981                    if value_or_stop!(children[i].is_nan_leaf()) {
1982                        replace_self_with!(&mut children[i]);
1983                        return SimplificationResult::Simplified;
1984                    }
1985                    let o = match children[i]
1986                        .compare(&children[result], PositivePercentageBasis::Unknown)
1987                    {
1988                        // We can't compare all the children, so we can't
1989                        // know which one will actually win. Bail out and
1990                        // keep ourselves as a min / max function.
1991                        //
1992                        // TODO: Maybe we could simplify compatible children,
1993                        // see https://github.com/w3c/csswg-drafts/issues/4756
1994                        None => return SimplificationResult::Unchanged,
1995                        Some(o) => o,
1996                    };
1997
1998                    if o == winning_order {
1999                        result = i;
2000                    }
2001                }
2002
2003                replace_self_with!(&mut children[result]);
2004                return SimplificationResult::Simplified;
2005            },
2006            Self::Sum(ref mut children_slot) => {
2007                let mut sums_to_merge = SmallVec::<[_; 3]>::new();
2008                let mut extra_kids = 0;
2009                for (i, child) in children_slot.iter().enumerate() {
2010                    if let Self::Sum(ref children) = *child {
2011                        extra_kids += children.len();
2012                        sums_to_merge.push(i);
2013                    }
2014                }
2015
2016                // If we only have one kid, we've already simplified it, and it
2017                // doesn't really matter whether it's a sum already or not, so
2018                // lift it up and continue.
2019                if children_slot.len() == 1 {
2020                    replace_self_with!(&mut children_slot[0]);
2021                    return SimplificationResult::Simplified;
2022                }
2023
2024                let mut children = mem::take(children_slot).into_vec();
2025
2026                if !sums_to_merge.is_empty() {
2027                    children.reserve(extra_kids - sums_to_merge.len());
2028                    // Merge all our nested sums, in reverse order so that the
2029                    // list indices are not invalidated.
2030                    for i in sums_to_merge.drain(..).rev() {
2031                        let kid_children = match children.swap_remove(i) {
2032                            Self::Sum(c) => c,
2033                            _ => unreachable!(),
2034                        };
2035
2036                        // This would be nicer with
2037                        // https://github.com/rust-lang/rust/issues/59878 fixed.
2038                        children.extend(kid_children.into_vec());
2039                    }
2040                }
2041
2042                let children_len = children.len();
2043                debug_assert!(children_len >= 2, "Should still have multiple kids!");
2044
2045                // Sort by spec order.
2046                children.sort_unstable_by_key(|c| c.sort_key());
2047
2048                // NOTE: if the function returns true, by the docs of dedup_by,
2049                // a is removed.
2050                children.dedup_by(|a, b| b.try_sum_in_place(a).is_ok());
2051
2052                let updated_children_len = children.len();
2053                if updated_children_len == 1 {
2054                    // If only one children remains, lift it up, and carry on.
2055                    replace_self_with!(&mut children[0]);
2056                } else {
2057                    // Else put our simplified children back.
2058                    *children_slot = children.into_boxed_slice().into();
2059                }
2060
2061                return if updated_children_len != children_len {
2062                    SimplificationResult::Simplified
2063                } else {
2064                    SimplificationResult::Unchanged
2065                };
2066            },
2067            Self::Product(ref mut children_slot) => {
2068                let mut products_to_merge = SmallVec::<[_; 3]>::new();
2069                let mut extra_kids = 0;
2070                for (i, child) in children_slot.iter().enumerate() {
2071                    if let Self::Product(ref children) = *child {
2072                        extra_kids += children.len();
2073                        products_to_merge.push(i);
2074                    }
2075                }
2076
2077                // If we only have one kid, we've already simplified it, and it
2078                // doesn't really matter whether it's a product already or not,
2079                // so lift it up and continue.
2080                if children_slot.len() == 1 {
2081                    replace_self_with!(&mut children_slot[0]);
2082                    return SimplificationResult::Unchanged;
2083                }
2084
2085                let mut children = mem::take(children_slot).into_vec();
2086                if !products_to_merge.is_empty() {
2087                    children.reserve(extra_kids - products_to_merge.len());
2088                    // Merge all our nested sums, in reverse order so that the
2089                    // list indices are not invalidated.
2090                    for i in products_to_merge.drain(..).rev() {
2091                        let kid_children = match children.swap_remove(i) {
2092                            Self::Product(c) => c,
2093                            _ => unreachable!(),
2094                        };
2095
2096                        // This would be nicer with
2097                        // https://github.com/rust-lang/rust/issues/59878 fixed.
2098                        children.extend(kid_children.into_vec());
2099                    }
2100                }
2101
2102                debug_assert!(children.len() >= 2, "Should still have multiple kids!");
2103
2104                // Sort by spec order.
2105                children.sort_unstable_by_key(|c| c.sort_key());
2106
2107                // NOTE: if the function returns true, by the docs of dedup_by,
2108                // a is removed.
2109                children.dedup_by(|right, left| left.try_product_in_place(right));
2110
2111                if children.len() == 1 {
2112                    // If only one children remains, lift it up, and carry on.
2113                    replace_self_with!(&mut children[0]);
2114                    return SimplificationResult::Simplified;
2115                } else {
2116                    // Else put our simplified children back.
2117                    *children_slot = children.into_boxed_slice().into();
2118                }
2119                return SimplificationResult::Unchanged;
2120            },
2121            Self::Sin(ref mut child) => {
2122                if let CalcNode::Leaf(ref leaf) = **child {
2123                    if let Some(radians) = leaf.as_number_or_angle_radians() {
2124                        let mut result = Self::Leaf(L::new_number(radians.sin()));
2125                        replace_self_with!(&mut result);
2126                        return SimplificationResult::Simplified;
2127                    }
2128                }
2129                return SimplificationResult::Unchanged;
2130            },
2131            Self::Cos(ref mut child) => {
2132                if let CalcNode::Leaf(ref leaf) = **child {
2133                    if let Some(radians) = leaf.as_number_or_angle_radians() {
2134                        let mut result = Self::Leaf(L::new_number(radians.cos()));
2135                        replace_self_with!(&mut result);
2136                        return SimplificationResult::Simplified;
2137                    }
2138                }
2139                return SimplificationResult::Unchanged;
2140            },
2141            Self::Tan(ref mut child) => {
2142                if let CalcNode::Leaf(ref leaf) = **child {
2143                    if let Some(radians) = leaf.as_number_or_angle_radians() {
2144                        let mut result = Self::Leaf(L::new_number(radians.tan()));
2145                        replace_self_with!(&mut result);
2146                        return SimplificationResult::Simplified;
2147                    }
2148                }
2149                return SimplificationResult::Unchanged;
2150            },
2151            Self::Asin(ref mut child) => {
2152                if let CalcNode::Leaf(ref leaf) = **child {
2153                    if let Some(value) = leaf.as_number() {
2154                        let mut result = Self::Leaf(L::new_angle_from_radians(value.asin()));
2155                        replace_self_with!(&mut result);
2156                        return SimplificationResult::Simplified;
2157                    }
2158                }
2159                return SimplificationResult::Unchanged;
2160            },
2161            Self::Acos(ref mut child) => {
2162                if let CalcNode::Leaf(ref leaf) = **child {
2163                    if let Some(value) = leaf.as_number() {
2164                        let mut result = Self::Leaf(L::new_angle_from_radians(value.acos()));
2165                        replace_self_with!(&mut result);
2166                        return SimplificationResult::Simplified;
2167                    }
2168                }
2169                return SimplificationResult::Unchanged;
2170            },
2171            Self::Atan(ref mut child) => {
2172                if let CalcNode::Leaf(ref leaf) = **child {
2173                    if let Some(value) = leaf.as_number() {
2174                        let mut result = Self::Leaf(L::new_angle_from_radians(value.atan()));
2175                        replace_self_with!(&mut result);
2176                        return SimplificationResult::Simplified;
2177                    }
2178                }
2179                return SimplificationResult::Unchanged;
2180            },
2181            Self::Atan2(ref mut a, ref mut b) => {
2182                if let (CalcNode::Leaf(ref la), CalcNode::Leaf(ref lb)) = (&**a, &**b) {
2183                    if la.is_same_unit_as(lb) {
2184                        if let (Some(a_val), Some(b_val)) =
2185                            (la.unitless_value(), lb.unitless_value())
2186                        {
2187                            let mut result =
2188                                Self::Leaf(L::new_angle_from_radians(a_val.atan2(b_val)));
2189                            replace_self_with!(&mut result);
2190                            return SimplificationResult::Simplified;
2191                        }
2192                    }
2193                }
2194                return SimplificationResult::Unchanged;
2195            },
2196            Self::Pow(ref mut a, ref mut b) => {
2197                if let (CalcNode::Leaf(ref la), CalcNode::Leaf(ref lb)) = (&**a, &**b) {
2198                    if let (Some(a_val), Some(b_val)) = (la.as_number(), lb.as_number()) {
2199                        let mut result = Self::Leaf(L::new_number(a_val.powf(b_val)));
2200                        replace_self_with!(&mut result);
2201                        return SimplificationResult::Simplified;
2202                    }
2203                }
2204                return SimplificationResult::Unchanged;
2205            },
2206            Self::Sqrt(ref mut child) => {
2207                if let CalcNode::Leaf(ref leaf) = **child {
2208                    if let Some(value) = leaf.as_number() {
2209                        let mut result = Self::Leaf(L::new_number(value.sqrt()));
2210                        replace_self_with!(&mut result);
2211                        return SimplificationResult::Simplified;
2212                    }
2213                }
2214                return SimplificationResult::Unchanged;
2215            },
2216            Self::Hypot(ref children) => {
2217                let mut result = value_or_stop!(children[0].try_op(&children[0], Mul::mul));
2218
2219                for child in children.iter().skip(1) {
2220                    let square = value_or_stop!(child.try_op(&child, Mul::mul));
2221                    result = value_or_stop!(result.try_op(&square, Add::add));
2222                }
2223
2224                result = value_or_stop!(result.try_op(&result, |a, _| a.sqrt()));
2225
2226                replace_self_with!(&mut result);
2227                return SimplificationResult::Simplified;
2228            },
2229            Self::Log(ref mut a, ref mut b) => {
2230                if let CalcNode::Leaf(ref la) = **a {
2231                    if let Some(a_val) = la.as_number() {
2232                        let folded = match b {
2233                            Optional::Some(ref b) => {
2234                                if let CalcNode::Leaf(ref lb) = **b {
2235                                    lb.as_number().map(|b_val| a_val.log(b_val))
2236                                } else {
2237                                    None
2238                                }
2239                            },
2240                            Optional::None => Some(a_val.ln()),
2241                        };
2242                        if let Some(number) = folded {
2243                            let mut result = Self::Leaf(L::new_number(number));
2244                            replace_self_with!(&mut result);
2245                            return SimplificationResult::Simplified;
2246                        }
2247                    }
2248                }
2249                return SimplificationResult::Unchanged;
2250            },
2251            Self::Exp(ref mut child) => {
2252                if let CalcNode::Leaf(ref leaf) = **child {
2253                    if let Some(value) = leaf.as_number() {
2254                        let mut result = Self::Leaf(L::new_number(value.exp()));
2255                        replace_self_with!(&mut result);
2256                        return SimplificationResult::Simplified;
2257                    }
2258                }
2259                return SimplificationResult::Unchanged;
2260            },
2261            Self::Abs(ref mut child) => {
2262                if let CalcNode::Leaf(leaf) = child.as_mut() {
2263                    value_or_stop!(leaf.map(|v| v.abs()));
2264                    replace_self_with!(&mut **child);
2265                    return SimplificationResult::Simplified;
2266                }
2267                return SimplificationResult::Unchanged;
2268            },
2269            Self::Sign(ref mut child) => {
2270                if let CalcNode::Leaf(leaf) = child.as_mut() {
2271                    let mut result = Self::Leaf(value_or_stop!(L::sign_from(leaf)));
2272                    replace_self_with!(&mut result);
2273                    return SimplificationResult::Simplified;
2274                }
2275                return SimplificationResult::Unchanged;
2276            },
2277            Self::Negate(ref mut child) => {
2278                // Step 6.
2279                match &mut **child {
2280                    CalcNode::Leaf(_) => {
2281                        // 1. If root’s child is a numeric value, return an equivalent numeric value, but
2282                        // with the value negated (0 - value).
2283                        child.negate();
2284                        replace_self_with!(&mut **child);
2285                        return SimplificationResult::Simplified;
2286                    },
2287                    CalcNode::Negate(value) => {
2288                        // 2. If root’s child is a Negate node, return the child’s child.
2289                        replace_self_with!(&mut **value);
2290                        return SimplificationResult::Simplified;
2291                    },
2292                    _ => {
2293                        // 3. Return root.
2294                        return SimplificationResult::Unchanged;
2295                    },
2296                }
2297            },
2298            Self::Invert(ref mut child) => {
2299                // Step 7.
2300                match &mut **child {
2301                    CalcNode::Leaf(leaf) => {
2302                        // 1. If root’s child is a number (not a percentage or dimension) return the
2303                        // reciprocal of the child’s value.
2304                        if leaf.unit().is_empty() {
2305                            value_or_stop!(child.map(|v| 1.0 / v));
2306                            replace_self_with!(&mut **child);
2307                            return SimplificationResult::Simplified;
2308                        }
2309                        return SimplificationResult::Unchanged;
2310                    },
2311                    CalcNode::Invert(value) => {
2312                        // 2. If root’s child is an Invert node, return the child’s child.
2313                        replace_self_with!(&mut **value);
2314                        return SimplificationResult::Simplified;
2315                    },
2316                    _ => {
2317                        // 3. Return root.
2318                        return SimplificationResult::Unchanged;
2319                    },
2320                }
2321            },
2322            Self::Progress {
2323                clamping_mode,
2324                ref mut value,
2325                ref mut start,
2326                ref mut end,
2327            } => {
2328                if let (
2329                    CalcNode::Leaf(ref value),
2330                    CalcNode::Leaf(ref start),
2331                    CalcNode::Leaf(ref end),
2332                ) = (&**value, &**start, &**end)
2333                {
2334                    if value.is_same_unit_as(start) && value.is_same_unit_as(end) {
2335                        if let (Some(value), Some(start), Some(end)) = (
2336                            value.unitless_value(),
2337                            start.unitless_value(),
2338                            end.unitless_value(),
2339                        ) {
2340                            let mut result = Self::Leaf(L::new_number(
2341                                clamping_mode.evaluate(value, start, end),
2342                            ));
2343                            replace_self_with!(&mut result);
2344                            return SimplificationResult::Simplified;
2345                        }
2346                    }
2347                }
2348                return SimplificationResult::Unchanged;
2349            },
2350            Self::Leaf(ref mut l) => {
2351                return l.simplify();
2352            },
2353            Self::Anchor(ref mut f) => {
2354                if let GenericAnchorSide::Percentage(ref mut n) = f.side {
2355                    n.simplify_and_sort();
2356                    return SimplificationResult::Simplified;
2357                }
2358                if let Some(fallback) = f.fallback.as_mut() {
2359                    return fallback.node.simplify_and_sort();
2360                }
2361                return SimplificationResult::Unchanged;
2362            },
2363            Self::AnchorSize(ref mut f) => {
2364                if let Some(fallback) = f.fallback.as_mut() {
2365                    return fallback.node.simplify_and_sort();
2366                }
2367                return SimplificationResult::Unchanged;
2368            },
2369        }
2370    }
2371
2372    /// Simplifies and sorts the kids in the whole calculation subtree.
2373    pub fn simplify_and_sort(&mut self) -> SimplificationResult {
2374        let mut res = SimplificationResult::Unchanged;
2375        self.visit_depth_first(|node| match node.simplify_and_sort_direct_children() {
2376            SimplificationResult::Simplified => {
2377                res = SimplificationResult::Simplified;
2378            },
2379            _ => {},
2380        });
2381        res
2382    }
2383
2384    fn to_css_impl<W>(&self, dest: &mut CssWriter<W>, level: ArgumentLevel) -> fmt::Result
2385    where
2386        W: Write,
2387    {
2388        let write_closing_paren = match self {
2389            Self::MinMax(_, op) => {
2390                dest.write_str(match op {
2391                    MinMaxOp::Max => "max(",
2392                    MinMaxOp::Min => "min(",
2393                })?;
2394                true
2395            },
2396            Self::Clamp { .. } => {
2397                dest.write_str("clamp(")?;
2398                true
2399            },
2400            Self::Round { strategy, .. } => {
2401                match strategy {
2402                    RoundingStrategy::Nearest => dest.write_str("round("),
2403                    RoundingStrategy::Up => dest.write_str("round(up, "),
2404                    RoundingStrategy::Down => dest.write_str("round(down, "),
2405                    RoundingStrategy::ToZero => dest.write_str("round(to-zero, "),
2406                }?;
2407
2408                true
2409            },
2410            Self::ModRem { op, .. } => {
2411                dest.write_str(match op {
2412                    ModRemOp::Mod => "mod(",
2413                    ModRemOp::Rem => "rem(",
2414                })?;
2415
2416                true
2417            },
2418            Self::Sin(_) => {
2419                dest.write_str("sin(")?;
2420                true
2421            },
2422            Self::Cos(_) => {
2423                dest.write_str("cos(")?;
2424                true
2425            },
2426            Self::Tan(_) => {
2427                dest.write_str("tan(")?;
2428                true
2429            },
2430            Self::Asin(_) => {
2431                dest.write_str("asin(")?;
2432                true
2433            },
2434            Self::Acos(_) => {
2435                dest.write_str("acos(")?;
2436                true
2437            },
2438            Self::Atan(_) => {
2439                dest.write_str("atan(")?;
2440                true
2441            },
2442            Self::Atan2(..) => {
2443                dest.write_str("atan2(")?;
2444                true
2445            },
2446            Self::Pow(..) => {
2447                dest.write_str("pow(")?;
2448                true
2449            },
2450            Self::Sqrt(_) => {
2451                dest.write_str("sqrt(")?;
2452                true
2453            },
2454            Self::Hypot(_) => {
2455                dest.write_str("hypot(")?;
2456                true
2457            },
2458            Self::Log(..) => {
2459                dest.write_str("log(")?;
2460                true
2461            },
2462            Self::Exp(_) => {
2463                dest.write_str("exp(")?;
2464                true
2465            },
2466            Self::Abs(_) => {
2467                dest.write_str("abs(")?;
2468                true
2469            },
2470            Self::Sign(_) => {
2471                dest.write_str("sign(")?;
2472                true
2473            },
2474            Self::Progress { .. } => {
2475                dest.write_str("progress(")?;
2476                true
2477            },
2478            Self::Negate(_) => {
2479                // We never generate a [`Negate`] node as the root of a calculation, only inside
2480                // [`Sum`] nodes as a child. Because negate nodes are handled by the [`Sum`] node
2481                // directly (see below), this node will never be serialized.
2482                debug_assert!(
2483                    false,
2484                    "We never serialize Negate nodes as they are handled inside Sum nodes."
2485                );
2486                dest.write_str("(-1 * ")?;
2487                true
2488            },
2489            Self::Invert(_) => {
2490                if matches!(level, ArgumentLevel::CalculationRoot) {
2491                    dest.write_str("calc")?;
2492                }
2493                dest.write_str("(1 / ")?;
2494                true
2495            },
2496            Self::Sum(_) | Self::Product(_) => match level {
2497                ArgumentLevel::CalculationRoot => {
2498                    dest.write_str("calc(")?;
2499                    true
2500                },
2501                ArgumentLevel::ArgumentRoot => false,
2502                ArgumentLevel::Nested => {
2503                    dest.write_str("(")?;
2504                    true
2505                },
2506            },
2507            Self::Leaf(leaf) => match level {
2508                ArgumentLevel::CalculationRoot => {
2509                    if leaf.should_serialize_with_root_calc_wrapper() {
2510                        dest.write_str("calc(")?;
2511                        true
2512                    } else {
2513                        false
2514                    }
2515                },
2516                ArgumentLevel::ArgumentRoot | ArgumentLevel::Nested => false,
2517            },
2518            Self::Anchor(_) | Self::AnchorSize(_) => false,
2519        };
2520
2521        match *self {
2522            Self::MinMax(ref children, _) | Self::Hypot(ref children) => {
2523                let mut first = true;
2524                for child in &**children {
2525                    if !first {
2526                        dest.write_str(", ")?;
2527                    }
2528                    first = false;
2529                    child.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2530                }
2531            },
2532            Self::Negate(ref value) | Self::Invert(ref value) => {
2533                value.to_css_impl(dest, ArgumentLevel::Nested)?
2534            },
2535            Self::Sum(ref children) => {
2536                let mut first = true;
2537                for child in &**children {
2538                    if !first {
2539                        match child {
2540                            Self::Leaf(l) => {
2541                                if let Ok(true) = l.is_negative() {
2542                                    dest.write_str(" - ")?;
2543                                    let mut negated = l.clone();
2544                                    // We can unwrap here, because we already
2545                                    // checked if the value inside is negative.
2546                                    negated.map(std::ops::Neg::neg).unwrap();
2547                                    negated.to_css(dest)?;
2548                                } else {
2549                                    dest.write_str(" + ")?;
2550                                    l.to_css(dest)?;
2551                                }
2552                            },
2553                            Self::Negate(n) => {
2554                                dest.write_str(" - ")?;
2555                                n.to_css_impl(dest, ArgumentLevel::Nested)?;
2556                            },
2557                            _ => {
2558                                dest.write_str(" + ")?;
2559                                child.to_css_impl(dest, ArgumentLevel::Nested)?;
2560                            },
2561                        }
2562                    } else {
2563                        first = false;
2564                        child.to_css_impl(dest, ArgumentLevel::Nested)?;
2565                    }
2566                }
2567            },
2568            Self::Product(ref children) => {
2569                let mut first = true;
2570                for child in &**children {
2571                    if !first {
2572                        match child {
2573                            Self::Invert(n) => {
2574                                dest.write_str(" / ")?;
2575                                n.to_css_impl(dest, ArgumentLevel::Nested)?;
2576                            },
2577                            _ => {
2578                                dest.write_str(" * ")?;
2579                                child.to_css_impl(dest, ArgumentLevel::Nested)?;
2580                            },
2581                        }
2582                    } else {
2583                        first = false;
2584                        child.to_css_impl(dest, ArgumentLevel::Nested)?;
2585                    }
2586                }
2587            },
2588            Self::Clamp {
2589                ref min,
2590                ref center,
2591                ref max,
2592            } => {
2593                min.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2594                dest.write_str(", ")?;
2595                center.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2596                dest.write_str(", ")?;
2597                max.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2598            },
2599            Self::Round {
2600                ref value,
2601                ref step,
2602                ..
2603            } => {
2604                value.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2605                dest.write_str(", ")?;
2606                step.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2607            },
2608            Self::ModRem {
2609                ref dividend,
2610                ref divisor,
2611                ..
2612            } => {
2613                dividend.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2614                dest.write_str(", ")?;
2615                divisor.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2616            },
2617            Self::Sin(ref v)
2618            | Self::Cos(ref v)
2619            | Self::Tan(ref v)
2620            | Self::Asin(ref v)
2621            | Self::Acos(ref v)
2622            | Self::Atan(ref v) => v.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?,
2623            Self::Atan2(ref a, ref b) => {
2624                a.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2625                dest.write_str(", ")?;
2626                b.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2627            },
2628            Self::Pow(ref a, ref b) => {
2629                a.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2630                dest.write_str(", ")?;
2631                b.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2632            },
2633            Self::Sqrt(ref v) | Self::Exp(ref v) => {
2634                v.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?
2635            },
2636            Self::Log(ref a, ref b) => {
2637                a.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2638                if let Optional::Some(ref b) = b {
2639                    dest.write_str(", ")?;
2640                    b.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2641                }
2642            },
2643            Self::Abs(ref v) | Self::Sign(ref v) => {
2644                v.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?
2645            },
2646            Self::Progress {
2647                clamping_mode,
2648                ref value,
2649                ref start,
2650                ref end,
2651            } => {
2652                if clamping_mode == ProgressClampingMode::NoClamp {
2653                    clamping_mode.to_css(dest)?;
2654                    dest.write_char(' ')?;
2655                }
2656                value.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2657                dest.write_str(", ")?;
2658                start.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2659                dest.write_str(", ")?;
2660                end.to_css_impl(dest, ArgumentLevel::ArgumentRoot)?;
2661            },
2662            Self::Leaf(ref l) => l.to_css(dest)?,
2663            Self::Anchor(ref f) => f.to_css(dest)?,
2664            Self::AnchorSize(ref f) => f.to_css(dest)?,
2665        }
2666
2667        if write_closing_paren {
2668            dest.write_char(')')?;
2669        }
2670        Ok(())
2671    }
2672
2673    fn to_typed_impl(
2674        &self,
2675        dest: &mut ThinVec<TypedValue>,
2676        level: ArgumentLevel,
2677    ) -> Result<(), ()> {
2678        // Note: Naturally, only nodes that can be reified into CSSUnitValue
2679        // and CSSMathValue objects are supported here:
2680        // Leaf, Negate, Invert, Sum, Product, MinMax, and Clamp.
2681        match *self {
2682            Self::Leaf(ref l) => match l.to_typed_value() {
2683                Some(TypedValue::Numeric(inner)) => {
2684                    match level {
2685                        ArgumentLevel::CalculationRoot => {
2686                            dest.push(TypedValue::Numeric(NumericValue::Math(MathValue::Sum(
2687                                MathSum::try_from_numeric_values(ThinVec::from([inner]))?,
2688                            ))));
2689                        },
2690                        ArgumentLevel::ArgumentRoot | ArgumentLevel::Nested => {
2691                            dest.push(TypedValue::Numeric(inner));
2692                        },
2693                    }
2694                    Ok(())
2695                },
2696                _ => Err(()),
2697            },
2698            Self::Negate(_) => {
2699                // We never generate a [`Negate`] node as the root of a calculation, only inside
2700                // [`Sum`] nodes as a child. Because negate nodes are handled by the [`Sum`] node
2701                // directly (see below), this node will never be reified.
2702                debug_assert!(
2703                    false,
2704                    "We never reify Negate nodes as they are handled inside Sum nodes."
2705                );
2706
2707                Err(())
2708            },
2709            Self::Invert(ref value) => {
2710                let inner = CalcNodeWithLevel::nested(value)
2711                    .to_numeric_value()
2712                    .ok_or(())?;
2713
2714                dest.push(TypedValue::Numeric(NumericValue::Math(MathValue::Invert(
2715                    Box::new(inner),
2716                ))));
2717                Ok(())
2718            },
2719            Self::Sum(ref children) => {
2720                let mut values = ThinVec::new();
2721                let mut first = true;
2722
2723                for child in &**children {
2724                    if !first {
2725                        match child {
2726                            Self::Leaf(l) => {
2727                                if let Ok(true) = l.is_negative() {
2728                                    let mut negated = l.clone();
2729
2730                                    // We can unwrap here, because we already
2731                                    // checked if the value inside is negative.
2732                                    negated.map(std::ops::Neg::neg).unwrap();
2733
2734                                    let inner = negated.to_numeric_value().ok_or(())?;
2735
2736                                    values.push(NumericValue::Math(MathValue::Negate(Box::new(
2737                                        inner,
2738                                    ))));
2739                                } else {
2740                                    let inner = l.to_numeric_value().ok_or(())?;
2741
2742                                    values.push(inner);
2743                                }
2744                            },
2745                            Self::Negate(n) => {
2746                                let inner = CalcNodeWithLevel::nested(n.as_ref())
2747                                    .to_numeric_value()
2748                                    .ok_or(())?;
2749
2750                                values.push(NumericValue::Math(MathValue::Negate(Box::new(inner))));
2751                            },
2752                            _ => {
2753                                let inner = CalcNodeWithLevel::nested(child)
2754                                    .to_numeric_value()
2755                                    .ok_or(())?;
2756
2757                                values.push(inner);
2758                            },
2759                        }
2760                    } else {
2761                        first = false;
2762
2763                        let inner = CalcNodeWithLevel::nested(child)
2764                            .to_numeric_value()
2765                            .ok_or(())?;
2766
2767                        values.push(inner);
2768                    }
2769                }
2770
2771                dest.push(TypedValue::Numeric(NumericValue::Math(MathValue::Sum(
2772                    MathSum::try_from_numeric_values(values)?,
2773                ))));
2774                Ok(())
2775            },
2776            Self::Product(ref children) => {
2777                let mut values = ThinVec::new();
2778                let mut first = true;
2779
2780                for child in &**children {
2781                    if !first {
2782                        match child {
2783                            Self::Invert(n) => {
2784                                let inner = CalcNodeWithLevel::nested(n.as_ref())
2785                                    .to_numeric_value()
2786                                    .ok_or(())?;
2787
2788                                values.push(NumericValue::Math(MathValue::Invert(Box::new(inner))));
2789                            },
2790                            _ => {
2791                                let inner = CalcNodeWithLevel::nested(child)
2792                                    .to_numeric_value()
2793                                    .ok_or(())?;
2794
2795                                values.push(inner);
2796                            },
2797                        }
2798                    } else {
2799                        first = false;
2800
2801                        let inner = CalcNodeWithLevel::nested(child)
2802                            .to_numeric_value()
2803                            .ok_or(())?;
2804
2805                        values.push(inner);
2806                    }
2807                }
2808
2809                dest.push(TypedValue::Numeric(NumericValue::Math(MathValue::Product(
2810                    values,
2811                ))));
2812                Ok(())
2813            },
2814            Self::MinMax(ref children, op) => {
2815                let mut values = ThinVec::new();
2816
2817                for child in &**children {
2818                    let inner = CalcNodeWithLevel::argument_root(child)
2819                        .to_numeric_value()
2820                        .ok_or(())?;
2821
2822                    values.push(inner);
2823                }
2824
2825                let math_value = match op {
2826                    MinMaxOp::Min => MathValue::Min(values),
2827                    MinMaxOp::Max => MathValue::Max(values),
2828                };
2829
2830                dest.push(TypedValue::Numeric(NumericValue::Math(math_value)));
2831                Ok(())
2832            },
2833            Self::Clamp {
2834                ref min,
2835                ref center,
2836                ref max,
2837            } => {
2838                let lower = CalcNodeWithLevel::argument_root(min)
2839                    .to_numeric_value()
2840                    .ok_or(())?;
2841
2842                let value = CalcNodeWithLevel::argument_root(center)
2843                    .to_numeric_value()
2844                    .ok_or(())?;
2845
2846                let upper = CalcNodeWithLevel::argument_root(max)
2847                    .to_numeric_value()
2848                    .ok_or(())?;
2849
2850                dest.push(TypedValue::Numeric(NumericValue::Math(MathValue::Clamp(
2851                    [lower, value, upper].into(),
2852                ))));
2853                Ok(())
2854            },
2855            _ => Err(()),
2856        }
2857    }
2858
2859    fn compare(
2860        &self,
2861        other: &Self,
2862        basis_positive: PositivePercentageBasis,
2863    ) -> Option<cmp::Ordering> {
2864        match (self, other) {
2865            (&CalcNode::Leaf(ref one), &CalcNode::Leaf(ref other)) => {
2866                one.compare(other, basis_positive)
2867            },
2868            _ => None,
2869        }
2870    }
2871
2872    compare_helpers!();
2873}
2874
2875impl<L: CalcNodeLeaf> ToCss for CalcNode<L> {
2876    /// <https://drafts.csswg.org/css-values/#calc-serialize>
2877    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
2878    where
2879        W: Write,
2880    {
2881        self.to_css_impl(dest, ArgumentLevel::CalculationRoot)
2882    }
2883}
2884
2885impl<L: CalcNodeLeaf> ToTyped for CalcNode<L> {
2886    fn to_typed(&self, dest: &mut ThinVec<TypedValue>) -> Result<(), ()> {
2887        CalcNodeWithLevel::calculation_root(self).to_typed(dest)
2888    }
2889}
2890
2891struct CalcNodeWithLevel<'a, L> {
2892    node: &'a CalcNode<L>,
2893    level: ArgumentLevel,
2894}
2895
2896impl<'a, L> CalcNodeWithLevel<'a, L> {
2897    #[inline]
2898    fn new(node: &'a CalcNode<L>, level: ArgumentLevel) -> Self {
2899        Self { node, level }
2900    }
2901
2902    #[inline]
2903    fn calculation_root(node: &'a CalcNode<L>) -> Self {
2904        Self::new(node, ArgumentLevel::CalculationRoot)
2905    }
2906
2907    #[inline]
2908    fn argument_root(node: &'a CalcNode<L>) -> Self {
2909        Self::new(node, ArgumentLevel::ArgumentRoot)
2910    }
2911
2912    #[inline]
2913    fn nested(node: &'a CalcNode<L>) -> Self {
2914        Self::new(node, ArgumentLevel::Nested)
2915    }
2916}
2917
2918impl<'a, L: CalcNodeLeaf> ToTyped for CalcNodeWithLevel<'a, L> {
2919    fn to_typed(&self, dest: &mut ThinVec<TypedValue>) -> Result<(), ()> {
2920        self.node.to_typed_impl(dest, self.level.clone())
2921    }
2922}
2923
2924#[cfg(test)]
2925mod tests {
2926    use super::*;
2927
2928    #[test]
2929    fn can_sum_with_checks() {
2930        assert!(CalcUnits::LENGTH.can_sum_with(CalcUnits::LENGTH));
2931        assert!(CalcUnits::LENGTH.can_sum_with(CalcUnits::PERCENTAGE));
2932        assert!(CalcUnits::LENGTH.can_sum_with(CalcUnits::LENGTH_PERCENTAGE));
2933
2934        assert!(CalcUnits::PERCENTAGE.can_sum_with(CalcUnits::LENGTH));
2935        assert!(CalcUnits::PERCENTAGE.can_sum_with(CalcUnits::PERCENTAGE));
2936        assert!(CalcUnits::PERCENTAGE.can_sum_with(CalcUnits::LENGTH_PERCENTAGE));
2937
2938        assert!(CalcUnits::LENGTH_PERCENTAGE.can_sum_with(CalcUnits::LENGTH));
2939        assert!(CalcUnits::LENGTH_PERCENTAGE.can_sum_with(CalcUnits::PERCENTAGE));
2940        assert!(CalcUnits::LENGTH_PERCENTAGE.can_sum_with(CalcUnits::LENGTH_PERCENTAGE));
2941
2942        assert!(!CalcUnits::ANGLE.can_sum_with(CalcUnits::TIME));
2943        assert!(CalcUnits::ANGLE.can_sum_with(CalcUnits::ANGLE));
2944
2945        assert!(!(CalcUnits::ANGLE | CalcUnits::TIME).can_sum_with(CalcUnits::ANGLE));
2946        assert!(!CalcUnits::ANGLE.can_sum_with(CalcUnits::ANGLE | CalcUnits::TIME));
2947        assert!(
2948            !(CalcUnits::ANGLE | CalcUnits::TIME).can_sum_with(CalcUnits::ANGLE | CalcUnits::TIME)
2949        );
2950    }
2951}