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