typst_library/foundations/
styles.rs

1use std::any::{Any, TypeId};
2use std::fmt::{self, Debug, Formatter};
3use std::hash::{Hash, Hasher};
4use std::{mem, ptr};
5
6use comemo::Tracked;
7use ecow::{eco_vec, EcoString, EcoVec};
8use smallvec::SmallVec;
9use typst_syntax::Span;
10use typst_utils::LazyHash;
11
12use crate::diag::{SourceResult, Trace, Tracepoint};
13use crate::engine::Engine;
14use crate::foundations::{
15    cast, ty, Content, Context, Element, Func, NativeElement, OneOrMultiple, Repr,
16    Selector,
17};
18use crate::text::{FontFamily, FontList, TextElem};
19
20/// A list of style properties.
21#[ty(cast)]
22#[derive(Default, PartialEq, Clone, Hash)]
23pub struct Styles(EcoVec<LazyHash<Style>>);
24
25impl Styles {
26    /// Create a new, empty style list.
27    pub const fn new() -> Self {
28        Self(EcoVec::new())
29    }
30
31    /// Whether this contains no styles.
32    pub fn is_empty(&self) -> bool {
33        self.0.is_empty()
34    }
35
36    /// Iterate over the contained styles.
37    pub fn iter(&self) -> impl Iterator<Item = &Style> {
38        self.0.iter().map(|style| &**style)
39    }
40
41    /// Iterate over the contained styles.
42    pub fn as_slice(&self) -> &[LazyHash<Style>] {
43        self.0.as_slice()
44    }
45
46    /// Set an inner value for a style property.
47    ///
48    /// If the property needs folding and the value is already contained in the
49    /// style map, `self` contributes the outer values and `value` is the inner
50    /// one.
51    pub fn set(&mut self, style: impl Into<Style>) {
52        self.0.push(LazyHash::new(style.into()));
53    }
54
55    /// Remove the style that was last set.
56    pub fn unset(&mut self) {
57        self.0.pop();
58    }
59
60    /// Apply outer styles. Like [`chain`](StyleChain::chain), but in-place.
61    pub fn apply(&mut self, mut outer: Self) {
62        outer.0.extend(mem::take(self).0);
63        *self = outer;
64    }
65
66    /// Apply one outer styles.
67    pub fn apply_one(&mut self, outer: Style) {
68        self.0.insert(0, LazyHash::new(outer));
69    }
70
71    /// Add an origin span to all contained properties.
72    pub fn spanned(mut self, span: Span) -> Self {
73        for entry in self.0.make_mut() {
74            if let Style::Property(property) = &mut **entry {
75                property.span = span;
76            }
77        }
78        self
79    }
80
81    /// Marks the styles as having been applied outside of any show rule.
82    pub fn outside(mut self) -> Self {
83        for entry in self.0.make_mut() {
84            match &mut **entry {
85                Style::Property(property) => property.outside = true,
86                Style::Recipe(recipe) => recipe.outside = true,
87                _ => {}
88            }
89        }
90        self
91    }
92
93    /// Marks the styles as being allowed to be lifted up to the page level.
94    pub fn liftable(mut self) -> Self {
95        for entry in self.0.make_mut() {
96            if let Style::Property(property) = &mut **entry {
97                property.liftable = true;
98            }
99        }
100        self
101    }
102
103    /// Whether there is a style for the given field of the given element.
104    pub fn has<T: NativeElement>(&self, field: u8) -> bool {
105        let elem = T::elem();
106        self.0
107            .iter()
108            .filter_map(|style| style.property())
109            .any(|property| property.is_of(elem) && property.id == field)
110    }
111
112    /// Set a font family composed of a preferred family and existing families
113    /// from a style chain.
114    pub fn set_family(&mut self, preferred: FontFamily, existing: StyleChain) {
115        self.set(TextElem::set_font(FontList(
116            std::iter::once(preferred)
117                .chain(TextElem::font_in(existing).into_iter().cloned())
118                .collect(),
119        )));
120    }
121}
122
123impl From<LazyHash<Style>> for Styles {
124    fn from(style: LazyHash<Style>) -> Self {
125        Self(eco_vec![style])
126    }
127}
128
129impl From<Style> for Styles {
130    fn from(style: Style) -> Self {
131        Self(eco_vec![LazyHash::new(style)])
132    }
133}
134
135impl IntoIterator for Styles {
136    type Item = LazyHash<Style>;
137    type IntoIter = ecow::vec::IntoIter<Self::Item>;
138
139    fn into_iter(self) -> Self::IntoIter {
140        self.0.into_iter()
141    }
142}
143
144impl FromIterator<LazyHash<Style>> for Styles {
145    fn from_iter<T: IntoIterator<Item = LazyHash<Style>>>(iter: T) -> Self {
146        Self(iter.into_iter().collect())
147    }
148}
149
150impl Debug for Styles {
151    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
152        f.write_str("Styles ")?;
153        f.debug_list().entries(&self.0).finish()
154    }
155}
156
157impl Repr for Styles {
158    fn repr(&self) -> EcoString {
159        "..".into()
160    }
161}
162
163/// A single style property or recipe.
164#[derive(Clone, Hash)]
165pub enum Style {
166    /// A style property originating from a set rule or constructor.
167    Property(Property),
168    /// A show rule recipe.
169    Recipe(Recipe),
170    /// Disables a specific show rule recipe.
171    ///
172    /// Note: This currently only works for regex recipes since it's the only
173    /// place we need it for the moment. Normal show rules use guards directly
174    /// on elements instead.
175    Revocation(RecipeIndex),
176}
177
178impl Style {
179    /// If this is a property, return it.
180    pub fn property(&self) -> Option<&Property> {
181        match self {
182            Self::Property(property) => Some(property),
183            _ => None,
184        }
185    }
186
187    /// If this is a recipe, return it.
188    pub fn recipe(&self) -> Option<&Recipe> {
189        match self {
190            Self::Recipe(recipe) => Some(recipe),
191            _ => None,
192        }
193    }
194
195    /// The style's span, if any.
196    pub fn span(&self) -> Span {
197        match self {
198            Self::Property(property) => property.span,
199            Self::Recipe(recipe) => recipe.span,
200            Self::Revocation(_) => Span::detached(),
201        }
202    }
203
204    /// Returns `Some(_)` with an optional span if this style is for
205    /// the given element.
206    pub fn element(&self) -> Option<Element> {
207        match self {
208            Style::Property(property) => Some(property.elem),
209            Style::Recipe(recipe) => match recipe.selector {
210                Some(Selector::Elem(elem, _)) => Some(elem),
211                _ => None,
212            },
213            Style::Revocation(_) => None,
214        }
215    }
216
217    /// Whether the style is allowed to be lifted up to the page level. Only
218    /// true for styles originating from set rules.
219    pub fn liftable(&self) -> bool {
220        match self {
221            Self::Property(property) => property.liftable,
222            Self::Recipe(_) => true,
223            Self::Revocation(_) => false,
224        }
225    }
226
227    /// Whether the style was applied outside of any show rule. This is set
228    /// during realization.
229    pub fn outside(&self) -> bool {
230        match self {
231            Self::Property(property) => property.outside,
232            Self::Recipe(recipe) => recipe.outside,
233            Self::Revocation(_) => false,
234        }
235    }
236
237    /// Turn this style into prehashed style.
238    pub fn wrap(self) -> LazyHash<Style> {
239        LazyHash::new(self)
240    }
241}
242
243impl Debug for Style {
244    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
245        match self {
246            Self::Property(property) => property.fmt(f),
247            Self::Recipe(recipe) => recipe.fmt(f),
248            Self::Revocation(guard) => guard.fmt(f),
249        }
250    }
251}
252
253impl From<Property> for Style {
254    fn from(property: Property) -> Self {
255        Self::Property(property)
256    }
257}
258
259impl From<Recipe> for Style {
260    fn from(recipe: Recipe) -> Self {
261        Self::Recipe(recipe)
262    }
263}
264
265/// A style property originating from a set rule or constructor.
266#[derive(Clone, Hash)]
267pub struct Property {
268    /// The element the property belongs to.
269    elem: Element,
270    /// The property's ID.
271    id: u8,
272    /// The property's value.
273    value: Block,
274    /// The span of the set rule the property stems from.
275    span: Span,
276    /// Whether the property is allowed to be lifted up to the page level.
277    liftable: bool,
278    /// Whether the property was applied outside of any show rule.
279    outside: bool,
280}
281
282impl Property {
283    /// Create a new property from a key-value pair.
284    pub fn new<E, T>(id: u8, value: T) -> Self
285    where
286        E: NativeElement,
287        T: Debug + Clone + Hash + Send + Sync + 'static,
288    {
289        Self {
290            elem: E::elem(),
291            id,
292            value: Block::new(value),
293            span: Span::detached(),
294            liftable: false,
295            outside: false,
296        }
297    }
298
299    /// Whether this property is the given one.
300    pub fn is(&self, elem: Element, id: u8) -> bool {
301        self.elem == elem && self.id == id
302    }
303
304    /// Whether this property belongs to the given element.
305    pub fn is_of(&self, elem: Element) -> bool {
306        self.elem == elem
307    }
308
309    /// Turn this property into prehashed style.
310    pub fn wrap(self) -> LazyHash<Style> {
311        Style::Property(self).wrap()
312    }
313}
314
315impl Debug for Property {
316    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
317        write!(
318            f,
319            "Set({}.{}: ",
320            self.elem.name(),
321            self.elem.field_name(self.id).unwrap()
322        )?;
323        self.value.fmt(f)?;
324        write!(f, ")")
325    }
326}
327
328/// A block storage for storing style values.
329///
330/// We're using a `Box` since values will either be contained in an `Arc` and
331/// therefore already on the heap or they will be small enough that we can just
332/// clone them.
333#[derive(Hash)]
334struct Block(Box<dyn Blockable>);
335
336impl Block {
337    /// Creates a new block.
338    fn new<T: Blockable>(value: T) -> Self {
339        Self(Box::new(value))
340    }
341
342    /// Downcasts the block to the specified type.
343    fn downcast<T: 'static>(&self) -> Option<&T> {
344        self.0.as_any().downcast_ref()
345    }
346}
347
348impl Debug for Block {
349    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
350        self.0.fmt(f)
351    }
352}
353
354impl Clone for Block {
355    fn clone(&self) -> Self {
356        self.0.dyn_clone()
357    }
358}
359
360/// A value that can be stored in a block.
361///
362/// Auto derived for all types that implement [`Any`], [`Clone`], [`Hash`],
363/// [`Debug`], [`Send`] and [`Sync`].
364trait Blockable: Debug + Send + Sync + 'static {
365    /// Equivalent to `downcast_ref` for the block.
366    fn as_any(&self) -> &dyn Any;
367
368    /// Equivalent to [`Hash`] for the block.
369    fn dyn_hash(&self, state: &mut dyn Hasher);
370
371    /// Equivalent to [`Clone`] for the block.
372    fn dyn_clone(&self) -> Block;
373}
374
375impl<T: Debug + Clone + Hash + Send + Sync + 'static> Blockable for T {
376    fn as_any(&self) -> &dyn Any {
377        self
378    }
379
380    fn dyn_hash(&self, mut state: &mut dyn Hasher) {
381        // Also hash the TypeId since values with different types but
382        // equal data should be different.
383        TypeId::of::<Self>().hash(&mut state);
384        self.hash(&mut state);
385    }
386
387    fn dyn_clone(&self) -> Block {
388        Block(Box::new(self.clone()))
389    }
390}
391
392impl Hash for dyn Blockable {
393    fn hash<H: Hasher>(&self, state: &mut H) {
394        self.dyn_hash(state);
395    }
396}
397
398/// A show rule recipe.
399#[derive(Clone, PartialEq, Hash)]
400pub struct Recipe {
401    /// Determines whether the recipe applies to an element.
402    ///
403    /// If this is `None`, then this recipe is from a show rule with
404    /// no selector (`show: rest => ...`), which is [eagerly applied][Content::styled_with_recipe]
405    /// to the rest of the content in the scope.
406    selector: Option<Selector>,
407    /// The transformation to perform on the match.
408    transform: Transformation,
409    /// The span that errors are reported with.
410    span: Span,
411    /// Relevant properties of the kind of construct the style originated from
412    /// and where it was applied.
413    outside: bool,
414}
415
416impl Recipe {
417    /// Create a new recipe from a key-value pair.
418    pub fn new(
419        selector: Option<Selector>,
420        transform: Transformation,
421        span: Span,
422    ) -> Self {
423        Self { selector, transform, span, outside: false }
424    }
425
426    /// The recipe's selector.
427    pub fn selector(&self) -> Option<&Selector> {
428        self.selector.as_ref()
429    }
430
431    /// The recipe's transformation.
432    pub fn transform(&self) -> &Transformation {
433        &self.transform
434    }
435
436    /// The recipe's span.
437    pub fn span(&self) -> Span {
438        self.span
439    }
440
441    /// Apply the recipe to the given content.
442    pub fn apply(
443        &self,
444        engine: &mut Engine,
445        context: Tracked<Context>,
446        content: Content,
447    ) -> SourceResult<Content> {
448        let mut content = match &self.transform {
449            Transformation::Content(content) => content.clone(),
450            Transformation::Func(func) => {
451                let mut result = func.call(engine, context, [content.clone()]);
452                if self.selector.is_some() {
453                    let point = || Tracepoint::Show(content.func().name().into());
454                    result = result.trace(engine.world, point, content.span());
455                }
456                result?.display()
457            }
458            Transformation::Style(styles) => content.styled_with_map(styles.clone()),
459        };
460        if content.span().is_detached() {
461            content = content.spanned(self.span);
462        }
463        Ok(content)
464    }
465}
466
467impl Debug for Recipe {
468    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
469        f.write_str("Show(")?;
470        if let Some(selector) = &self.selector {
471            selector.fmt(f)?;
472            f.write_str(", ")?;
473        }
474        self.transform.fmt(f)
475    }
476}
477
478/// Identifies a show rule recipe from the top of the chain.
479#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
480pub struct RecipeIndex(pub usize);
481
482/// A show rule transformation that can be applied to a match.
483#[derive(Clone, PartialEq, Hash)]
484pub enum Transformation {
485    /// Replacement content.
486    Content(Content),
487    /// A function to apply to the match.
488    Func(Func),
489    /// Apply styles to the content.
490    Style(Styles),
491}
492
493impl Debug for Transformation {
494    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
495        match self {
496            Self::Content(content) => content.fmt(f),
497            Self::Func(func) => func.fmt(f),
498            Self::Style(styles) => styles.fmt(f),
499        }
500    }
501}
502
503cast! {
504    Transformation,
505    content: Content => Self::Content(content),
506    func: Func => Self::Func(func),
507}
508
509/// A chain of styles, similar to a linked list.
510///
511/// A style chain allows to combine properties from multiple style lists in a
512/// element hierarchy in a non-allocating way. Rather than eagerly merging the
513/// lists, each access walks the hierarchy from the innermost to the outermost
514/// map, trying to find a match and then folding it with matches further up the
515/// chain.
516#[derive(Default, Clone, Copy, Hash)]
517pub struct StyleChain<'a> {
518    /// The first link of this chain.
519    head: &'a [LazyHash<Style>],
520    /// The remaining links in the chain.
521    tail: Option<&'a Self>,
522}
523
524impl<'a> StyleChain<'a> {
525    /// Start a new style chain with root styles.
526    pub fn new(root: &'a Styles) -> Self {
527        Self { head: &root.0, tail: None }
528    }
529
530    /// Make the given chainable the first link of this chain.
531    ///
532    /// The resulting style chain contains styles from `local` as well as
533    /// `self`. The ones from `local` take precedence over the ones from
534    /// `self`. For folded properties `local` contributes the inner value.
535    pub fn chain<'b, C>(&'b self, local: &'b C) -> StyleChain<'b>
536    where
537        C: Chainable + ?Sized,
538    {
539        Chainable::chain(local, self)
540    }
541
542    /// Cast the first value for the given property in the chain.
543    pub fn get<T: Clone + 'static>(
544        self,
545        func: Element,
546        id: u8,
547        inherent: Option<&T>,
548        default: impl Fn() -> T,
549    ) -> T {
550        self.properties::<T>(func, id, inherent)
551            .next()
552            .cloned()
553            .unwrap_or_else(default)
554    }
555
556    /// Cast the first value for the given property in the chain,
557    /// returning a borrowed value.
558    pub fn get_ref<T: 'static>(
559        self,
560        func: Element,
561        id: u8,
562        inherent: Option<&'a T>,
563        default: impl Fn() -> &'a T,
564    ) -> &'a T {
565        self.properties::<T>(func, id, inherent)
566            .next()
567            .unwrap_or_else(default)
568    }
569
570    /// Cast the first value for the given property in the chain, taking
571    /// `Fold` implementations into account.
572    pub fn get_folded<T: Fold + Clone + 'static>(
573        self,
574        func: Element,
575        id: u8,
576        inherent: Option<&T>,
577        default: impl Fn() -> T,
578    ) -> T {
579        fn next<T: Fold>(
580            mut values: impl Iterator<Item = T>,
581            default: &impl Fn() -> T,
582        ) -> T {
583            values
584                .next()
585                .map(|value| value.fold(next(values, default)))
586                .unwrap_or_else(default)
587        }
588        next(self.properties::<T>(func, id, inherent).cloned(), &default)
589    }
590
591    /// Iterate over all values for the given property in the chain.
592    fn properties<T: 'static>(
593        self,
594        func: Element,
595        id: u8,
596        inherent: Option<&'a T>,
597    ) -> impl Iterator<Item = &'a T> {
598        inherent.into_iter().chain(
599            self.entries()
600                .filter_map(|style| style.property())
601                .filter(move |property| property.is(func, id))
602                .map(|property| &property.value)
603                .map(move |value| {
604                    value.downcast().unwrap_or_else(|| {
605                        panic!(
606                            "attempted to read a value of a different type than was written {}.{}: {:?}",
607                            func.name(),
608                            func.field_name(id).unwrap(),
609                            value
610                        )
611                    })
612                }),
613        )
614    }
615
616    /// Iterate over the entries of the chain.
617    pub fn entries(self) -> Entries<'a> {
618        Entries { inner: [].as_slice().iter(), links: self.links() }
619    }
620
621    /// Iterate over the recipes in the chain.
622    pub fn recipes(self) -> impl Iterator<Item = &'a Recipe> {
623        self.entries().filter_map(|style| style.recipe())
624    }
625
626    /// Iterate over the links of the chain.
627    pub fn links(self) -> Links<'a> {
628        Links(Some(self))
629    }
630
631    /// Convert to a style map.
632    pub fn to_map(self) -> Styles {
633        let mut styles: EcoVec<_> = self.entries().cloned().collect();
634        styles.make_mut().reverse();
635        Styles(styles)
636    }
637
638    /// Build owned styles from the suffix (all links beyond the `len`) of the
639    /// chain.
640    pub fn suffix(self, len: usize) -> Styles {
641        let mut styles = EcoVec::new();
642        let take = self.links().count().saturating_sub(len);
643        for link in self.links().take(take) {
644            styles.extend(link.iter().cloned().rev());
645        }
646        styles.make_mut().reverse();
647        Styles(styles)
648    }
649
650    /// Remove the last link from the chain.
651    pub fn pop(&mut self) {
652        *self = self.tail.copied().unwrap_or_default();
653    }
654
655    /// Determine the shared trunk of a collection of style chains.
656    pub fn trunk(iter: impl IntoIterator<Item = Self>) -> Option<Self> {
657        // Determine shared style depth and first span.
658        let mut iter = iter.into_iter();
659        let mut trunk = iter.next()?;
660        let mut depth = trunk.links().count();
661
662        for mut chain in iter {
663            let len = chain.links().count();
664            if len < depth {
665                for _ in 0..depth - len {
666                    trunk.pop();
667                }
668                depth = len;
669            } else if len > depth {
670                for _ in 0..len - depth {
671                    chain.pop();
672                }
673            }
674
675            while depth > 0 && chain != trunk {
676                trunk.pop();
677                chain.pop();
678                depth -= 1;
679            }
680        }
681
682        Some(trunk)
683    }
684}
685
686impl Debug for StyleChain<'_> {
687    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
688        f.write_str("StyleChain ")?;
689        f.debug_list()
690            .entries(self.entries().collect::<Vec<_>>().into_iter().rev())
691            .finish()
692    }
693}
694
695impl PartialEq for StyleChain<'_> {
696    fn eq(&self, other: &Self) -> bool {
697        ptr::eq(self.head, other.head)
698            && match (self.tail, other.tail) {
699                (Some(a), Some(b)) => ptr::eq(a, b),
700                (None, None) => true,
701                _ => false,
702            }
703    }
704}
705
706/// Things that can be attached to a style chain.
707pub trait Chainable {
708    /// Attach `self` as the first link of the chain.
709    fn chain<'a>(&'a self, outer: &'a StyleChain<'_>) -> StyleChain<'a>;
710}
711
712impl Chainable for LazyHash<Style> {
713    fn chain<'a>(&'a self, outer: &'a StyleChain<'_>) -> StyleChain<'a> {
714        StyleChain {
715            head: std::slice::from_ref(self),
716            tail: Some(outer),
717        }
718    }
719}
720
721impl Chainable for [LazyHash<Style>] {
722    fn chain<'a>(&'a self, outer: &'a StyleChain<'_>) -> StyleChain<'a> {
723        if self.is_empty() {
724            *outer
725        } else {
726            StyleChain { head: self, tail: Some(outer) }
727        }
728    }
729}
730
731impl<const N: usize> Chainable for [LazyHash<Style>; N] {
732    fn chain<'a>(&'a self, outer: &'a StyleChain<'_>) -> StyleChain<'a> {
733        Chainable::chain(self.as_slice(), outer)
734    }
735}
736
737impl Chainable for Styles {
738    fn chain<'a>(&'a self, outer: &'a StyleChain<'_>) -> StyleChain<'a> {
739        Chainable::chain(self.0.as_slice(), outer)
740    }
741}
742
743/// An iterator over the entries in a style chain.
744pub struct Entries<'a> {
745    inner: std::slice::Iter<'a, LazyHash<Style>>,
746    links: Links<'a>,
747}
748
749impl<'a> Iterator for Entries<'a> {
750    type Item = &'a LazyHash<Style>;
751
752    fn next(&mut self) -> Option<Self::Item> {
753        loop {
754            if let Some(entry) = self.inner.next_back() {
755                return Some(entry);
756            }
757
758            match self.links.next() {
759                Some(next) => self.inner = next.iter(),
760                None => return None,
761            }
762        }
763    }
764}
765
766/// An iterator over the links of a style chain.
767pub struct Links<'a>(Option<StyleChain<'a>>);
768
769impl<'a> Iterator for Links<'a> {
770    type Item = &'a [LazyHash<Style>];
771
772    fn next(&mut self) -> Option<Self::Item> {
773        let StyleChain { head, tail } = self.0?;
774        self.0 = tail.copied();
775        Some(head)
776    }
777}
778
779/// A property that is resolved with other properties from the style chain.
780pub trait Resolve {
781    /// The type of the resolved output.
782    type Output;
783
784    /// Resolve the value using the style chain.
785    fn resolve(self, styles: StyleChain) -> Self::Output;
786}
787
788impl<T: Resolve> Resolve for Option<T> {
789    type Output = Option<T::Output>;
790
791    fn resolve(self, styles: StyleChain) -> Self::Output {
792        self.map(|v| v.resolve(styles))
793    }
794}
795
796/// A property that is folded to determine its final value.
797///
798/// In the example below, the chain of stroke values is folded into a single
799/// value: `4pt + red`.
800///
801/// ```example
802/// #set rect(stroke: red)
803/// #set rect(stroke: 4pt)
804/// #rect()
805/// ```
806pub trait Fold {
807    /// Fold this inner value with an outer folded value.
808    fn fold(self, outer: Self) -> Self;
809}
810
811impl Fold for bool {
812    fn fold(self, _: Self) -> Self {
813        self
814    }
815}
816
817impl<T: Fold> Fold for Option<T> {
818    fn fold(self, outer: Self) -> Self {
819        match (self, outer) {
820            (Some(inner), Some(outer)) => Some(inner.fold(outer)),
821            // An explicit `None` should be respected, thus we don't do
822            // `inner.or(outer)`.
823            (inner, _) => inner,
824        }
825    }
826}
827
828impl<T> Fold for Vec<T> {
829    fn fold(self, mut outer: Self) -> Self {
830        outer.extend(self);
831        outer
832    }
833}
834
835impl<T, const N: usize> Fold for SmallVec<[T; N]> {
836    fn fold(self, mut outer: Self) -> Self {
837        outer.extend(self);
838        outer
839    }
840}
841
842impl<T> Fold for OneOrMultiple<T> {
843    fn fold(self, mut outer: Self) -> Self {
844        outer.0.extend(self.0);
845        outer
846    }
847}
848
849/// A variant of fold for foldable optional (`Option<T>`) values where an inner
850/// `None` value isn't respected (contrary to `Option`'s usual `Fold`
851/// implementation, with which folding with an inner `None` always returns
852/// `None`). Instead, when either of the `Option` objects is `None`, the other
853/// one is necessarily returned by `fold_or`. Normal folding still occurs when
854/// both values are `Some`, using `T`'s `Fold` implementation.
855///
856/// This is useful when `None` in a particular context means "unspecified"
857/// rather than "absent", in which case a specified value (`Some`) is chosen
858/// over an unspecified one (`None`), while two specified values are folded
859/// together.
860pub trait AlternativeFold {
861    /// Attempts to fold this inner value with an outer value. However, if
862    /// either value is `None`, returns the other one instead of folding.
863    fn fold_or(self, outer: Self) -> Self;
864}
865
866impl<T: Fold> AlternativeFold for Option<T> {
867    fn fold_or(self, outer: Self) -> Self {
868        match (self, outer) {
869            (Some(inner), Some(outer)) => Some(inner.fold(outer)),
870            // If one of values is `None`, return the other one instead of
871            // folding.
872            (inner, outer) => inner.or(outer),
873        }
874    }
875}
876
877/// A type that accumulates depth when folded.
878#[derive(Debug, Default, Clone, Copy, PartialEq, Hash)]
879pub struct Depth(pub usize);
880
881impl Fold for Depth {
882    fn fold(self, outer: Self) -> Self {
883        Self(outer.0 + self.0)
884    }
885}