datafusion_physical_expr_common/
sort_expr.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! Sort expressions
19
20use std::cmp::Ordering;
21use std::fmt::{self, Display, Formatter};
22use std::hash::{Hash, Hasher};
23use std::ops::{Deref, DerefMut};
24use std::sync::Arc;
25use std::vec::IntoIter;
26
27use crate::physical_expr::{fmt_sql, PhysicalExpr};
28
29use arrow::compute::kernels::sort::{SortColumn, SortOptions};
30use arrow::datatypes::Schema;
31use arrow::record_batch::RecordBatch;
32use datafusion_common::{HashSet, Result};
33use datafusion_expr_common::columnar_value::ColumnarValue;
34
35/// Represents Sort operation for a column in a RecordBatch
36///
37/// Example:
38/// ```
39/// # use std::any::Any;
40/// # use std::collections::HashMap;
41/// # use std::fmt::{Display, Formatter};
42/// # use std::hash::Hasher;
43/// # use std::sync::Arc;
44/// # use arrow::array::RecordBatch;
45/// # use datafusion_common::Result;
46/// # use arrow::compute::SortOptions;
47/// # use arrow::datatypes::{DataType, Field, FieldRef, Schema};
48/// # use datafusion_expr_common::columnar_value::ColumnarValue;
49/// # use datafusion_physical_expr_common::physical_expr::PhysicalExpr;
50/// # use datafusion_physical_expr_common::sort_expr::PhysicalSortExpr;
51/// # // this crate doesn't have a physical expression implementation
52/// # // so make a really simple one
53/// # #[derive(Clone, Debug, PartialEq, Eq, Hash)]
54/// # struct MyPhysicalExpr;
55/// # impl PhysicalExpr for MyPhysicalExpr {
56/// #  fn as_any(&self) -> &dyn Any {todo!() }
57/// #  fn data_type(&self, input_schema: &Schema) -> Result<DataType> {todo!()}
58/// #  fn nullable(&self, input_schema: &Schema) -> Result<bool> {todo!() }
59/// #  fn evaluate(&self, batch: &RecordBatch) -> Result<ColumnarValue> {todo!() }
60/// #  fn return_field(&self, input_schema: &Schema) -> Result<FieldRef> { unimplemented!() }
61/// #  fn children(&self) -> Vec<&Arc<dyn PhysicalExpr>> {todo!()}
62/// #  fn with_new_children(self: Arc<Self>, children: Vec<Arc<dyn PhysicalExpr>>) -> Result<Arc<dyn PhysicalExpr>> {todo!()}
63/// # fn fmt_sql(&self, f: &mut Formatter<'_>) -> std::fmt::Result { todo!() }
64/// # }
65/// # impl Display for MyPhysicalExpr {
66/// #    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "a") }
67/// # }
68/// # fn col(name: &str) -> Arc<dyn PhysicalExpr> { Arc::new(MyPhysicalExpr) }
69/// // Sort by a ASC
70/// let options = SortOptions::default();
71/// let sort_expr = PhysicalSortExpr::new(col("a"), options);
72/// assert_eq!(sort_expr.to_string(), "a ASC");
73///
74/// // Sort by a DESC NULLS LAST
75/// let sort_expr = PhysicalSortExpr::new_default(col("a"))
76///   .desc()
77///   .nulls_last();
78/// assert_eq!(sort_expr.to_string(), "a DESC NULLS LAST");
79/// ```
80#[derive(Clone, Debug, Eq)]
81pub struct PhysicalSortExpr {
82    /// Physical expression representing the column to sort
83    pub expr: Arc<dyn PhysicalExpr>,
84    /// Option to specify how the given column should be sorted
85    pub options: SortOptions,
86}
87
88impl PhysicalSortExpr {
89    /// Create a new PhysicalSortExpr
90    pub fn new(expr: Arc<dyn PhysicalExpr>, options: SortOptions) -> Self {
91        Self { expr, options }
92    }
93
94    /// Create a new PhysicalSortExpr with default [`SortOptions`]
95    pub fn new_default(expr: Arc<dyn PhysicalExpr>) -> Self {
96        Self::new(expr, SortOptions::default())
97    }
98
99    /// Reverses the sort expression. For instance, `[a ASC NULLS LAST]` turns
100    /// into `[a DESC NULLS FIRST]`. Such reversals are useful in planning, e.g.
101    /// when constructing equivalent window expressions.
102    pub fn reverse(&self) -> Self {
103        let mut result = self.clone();
104        result.options = !result.options;
105        result
106    }
107
108    /// Set the sort sort options to ASC
109    pub fn asc(mut self) -> Self {
110        self.options.descending = false;
111        self
112    }
113
114    /// Set the sort sort options to DESC
115    pub fn desc(mut self) -> Self {
116        self.options.descending = true;
117        self
118    }
119
120    /// Set the sort sort options to NULLS FIRST
121    pub fn nulls_first(mut self) -> Self {
122        self.options.nulls_first = true;
123        self
124    }
125
126    /// Set the sort sort options to NULLS LAST
127    pub fn nulls_last(mut self) -> Self {
128        self.options.nulls_first = false;
129        self
130    }
131
132    /// Like [`PhysicalExpr::fmt_sql`] prints a [`PhysicalSortExpr`] in a SQL-like format.
133    pub fn fmt_sql(&self, f: &mut Formatter) -> fmt::Result {
134        write!(
135            f,
136            "{} {}",
137            fmt_sql(self.expr.as_ref()),
138            to_str(&self.options)
139        )
140    }
141
142    /// Evaluates the sort expression into a `SortColumn` that can be passed
143    /// into the arrow sort kernel.
144    pub fn evaluate_to_sort_column(&self, batch: &RecordBatch) -> Result<SortColumn> {
145        let array_to_sort = match self.expr.evaluate(batch)? {
146            ColumnarValue::Array(array) => array,
147            ColumnarValue::Scalar(scalar) => scalar.to_array_of_size(batch.num_rows())?,
148        };
149        Ok(SortColumn {
150            values: array_to_sort,
151            options: Some(self.options),
152        })
153    }
154
155    /// Checks whether this sort expression satisfies the given `requirement`.
156    /// If sort options are unspecified in `requirement`, only expressions are
157    /// compared for inequality. See [`options_compatible`] for details on
158    /// how sort options compare with one another.
159    pub fn satisfy(
160        &self,
161        requirement: &PhysicalSortRequirement,
162        schema: &Schema,
163    ) -> bool {
164        self.expr.eq(&requirement.expr)
165            && requirement.options.is_none_or(|opts| {
166                options_compatible(
167                    &self.options,
168                    &opts,
169                    self.expr.nullable(schema).unwrap_or(true),
170                )
171            })
172    }
173
174    /// Checks whether this sort expression satisfies the given `sort_expr`.
175    /// See [`options_compatible`] for details on how sort options compare with
176    /// one another.
177    pub fn satisfy_expr(&self, sort_expr: &Self, schema: &Schema) -> bool {
178        self.expr.eq(&sort_expr.expr)
179            && options_compatible(
180                &self.options,
181                &sort_expr.options,
182                self.expr.nullable(schema).unwrap_or(true),
183            )
184    }
185}
186
187impl PartialEq for PhysicalSortExpr {
188    fn eq(&self, other: &Self) -> bool {
189        self.options == other.options && self.expr.eq(&other.expr)
190    }
191}
192
193impl Hash for PhysicalSortExpr {
194    fn hash<H: Hasher>(&self, state: &mut H) {
195        self.expr.hash(state);
196        self.options.hash(state);
197    }
198}
199
200impl Display for PhysicalSortExpr {
201    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
202        write!(f, "{} {}", self.expr, to_str(&self.options))
203    }
204}
205
206/// Returns whether the given two [`SortOptions`] are compatible. Here,
207/// compatibility means that they are either exactly equal, or they differ only
208/// in whether NULL values come in first/last, which is immaterial because the
209/// column in question is not nullable (specified by the `nullable` parameter).
210pub fn options_compatible(
211    options_lhs: &SortOptions,
212    options_rhs: &SortOptions,
213    nullable: bool,
214) -> bool {
215    if nullable {
216        options_lhs == options_rhs
217    } else {
218        // If the column is not nullable, NULLS FIRST/LAST is not important.
219        options_lhs.descending == options_rhs.descending
220    }
221}
222
223/// Represents sort requirement associated with a plan
224///
225/// If the requirement includes [`SortOptions`] then both the
226/// expression *and* the sort options must match.
227///
228/// If the requirement does not include [`SortOptions`]) then only the
229/// expressions must match.
230///
231/// # Examples
232///
233/// With sort options (`A`, `DESC NULLS FIRST`):
234/// * `ORDER BY A DESC NULLS FIRST` matches
235/// * `ORDER BY A ASC  NULLS FIRST` does not match (`ASC` vs `DESC`)
236/// * `ORDER BY B DESC NULLS FIRST` does not match (different expr)
237///
238/// Without sort options (`A`, None):
239/// * `ORDER BY A DESC NULLS FIRST` matches
240/// * `ORDER BY A ASC  NULLS FIRST` matches (`ASC` and `NULL` options ignored)
241/// * `ORDER BY B DESC NULLS FIRST` does not match  (different expr)
242#[derive(Clone, Debug)]
243pub struct PhysicalSortRequirement {
244    /// Physical expression representing the column to sort
245    pub expr: Arc<dyn PhysicalExpr>,
246    /// Option to specify how the given column should be sorted.
247    /// If unspecified, there are no constraints on sort options.
248    pub options: Option<SortOptions>,
249}
250
251impl PartialEq for PhysicalSortRequirement {
252    fn eq(&self, other: &Self) -> bool {
253        self.options == other.options && self.expr.eq(&other.expr)
254    }
255}
256
257impl Display for PhysicalSortRequirement {
258    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
259        let opts_string = self.options.as_ref().map_or("NA", to_str);
260        write!(f, "{} {}", self.expr, opts_string)
261    }
262}
263
264/// Writes a list of [`PhysicalSortRequirement`]s to a `std::fmt::Formatter`.
265///
266/// Example output: `[a + 1, b]`
267pub fn format_physical_sort_requirement_list(
268    exprs: &[PhysicalSortRequirement],
269) -> impl Display + '_ {
270    struct DisplayWrapper<'a>(&'a [PhysicalSortRequirement]);
271    impl Display for DisplayWrapper<'_> {
272        fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
273            let mut iter = self.0.iter();
274            write!(f, "[")?;
275            if let Some(expr) = iter.next() {
276                write!(f, "{expr}")?;
277            }
278            for expr in iter {
279                write!(f, ", {expr}")?;
280            }
281            write!(f, "]")?;
282            Ok(())
283        }
284    }
285    DisplayWrapper(exprs)
286}
287
288impl PhysicalSortRequirement {
289    /// Creates a new requirement.
290    ///
291    /// If `options` is `Some(..)`, creates an `exact` requirement,
292    /// which must match both `options` and `expr`.
293    ///
294    /// If `options` is `None`, Creates a new `expr_only` requirement,
295    /// which must match only `expr`.
296    ///
297    /// See [`PhysicalSortRequirement`] for examples.
298    pub fn new(expr: Arc<dyn PhysicalExpr>, options: Option<SortOptions>) -> Self {
299        Self { expr, options }
300    }
301
302    /// Returns whether this requirement is equal or more specific than `other`.
303    pub fn compatible(&self, other: &Self) -> bool {
304        self.expr.eq(&other.expr)
305            && other
306                .options
307                .is_none_or(|other_opts| self.options == Some(other_opts))
308    }
309}
310
311/// Returns the SQL string representation of the given [`SortOptions`] object.
312#[inline]
313fn to_str(options: &SortOptions) -> &str {
314    match (options.descending, options.nulls_first) {
315        (true, true) => "DESC",
316        (true, false) => "DESC NULLS LAST",
317        (false, true) => "ASC",
318        (false, false) => "ASC NULLS LAST",
319    }
320}
321
322// Cross-conversion utilities between `PhysicalSortExpr` and `PhysicalSortRequirement`
323impl From<PhysicalSortExpr> for PhysicalSortRequirement {
324    fn from(value: PhysicalSortExpr) -> Self {
325        Self::new(value.expr, Some(value.options))
326    }
327}
328
329impl From<PhysicalSortRequirement> for PhysicalSortExpr {
330    /// The default sort options `ASC, NULLS LAST` when the requirement does
331    /// not specify sort options. This default is consistent with PostgreSQL.
332    ///
333    /// Reference: <https://www.postgresql.org/docs/current/queries-order.html>
334    fn from(value: PhysicalSortRequirement) -> Self {
335        let options = value
336            .options
337            .unwrap_or_else(|| SortOptions::new(false, false));
338        Self::new(value.expr, options)
339    }
340}
341
342/// This object represents a lexicographical ordering and contains a vector
343/// of `PhysicalSortExpr` objects.
344///
345/// For example, a `vec![a ASC, b DESC]` represents a lexicographical ordering
346/// that first sorts by column `a` in ascending order, then by column `b` in
347/// descending order.
348///
349/// # Invariants
350///
351/// The following always hold true for a `LexOrdering`:
352///
353/// 1. It is non-degenerate, meaning it contains at least one element.
354/// 2. It is duplicate-free, meaning it does not contain multiple entries for
355///    the same column.
356#[derive(Debug, Clone, PartialEq, Eq)]
357pub struct LexOrdering {
358    /// Vector of sort expressions representing the lexicographical ordering.
359    exprs: Vec<PhysicalSortExpr>,
360    /// Set of expressions in the lexicographical ordering, used to ensure
361    /// that the ordering is duplicate-free. Note that the elements in this
362    /// set are the same underlying physical expressions as in `exprs`.
363    set: HashSet<Arc<dyn PhysicalExpr>>,
364}
365
366impl LexOrdering {
367    /// Creates a new [`LexOrdering`] from the given vector of sort expressions.
368    /// If the vector is empty, returns `None`.
369    pub fn new(exprs: impl IntoIterator<Item = PhysicalSortExpr>) -> Option<Self> {
370        let (non_empty, ordering) = Self::construct(exprs);
371        non_empty.then_some(ordering)
372    }
373
374    /// Appends an element to the back of the `LexOrdering`.
375    pub fn push(&mut self, sort_expr: PhysicalSortExpr) {
376        if self.set.insert(Arc::clone(&sort_expr.expr)) {
377            self.exprs.push(sort_expr);
378        }
379    }
380
381    /// Add all elements from `iter` to the `LexOrdering`.
382    pub fn extend(&mut self, sort_exprs: impl IntoIterator<Item = PhysicalSortExpr>) {
383        for sort_expr in sort_exprs {
384            self.push(sort_expr);
385        }
386    }
387
388    /// Returns the leading `PhysicalSortExpr` of the `LexOrdering`. Note that
389    /// this function does not return an `Option`, as a `LexOrdering` is always
390    /// non-degenerate (i.e. it contains at least one element).
391    pub fn first(&self) -> &PhysicalSortExpr {
392        // Can safely `unwrap` because `LexOrdering` is non-degenerate:
393        self.exprs.first().unwrap()
394    }
395
396    /// Returns the number of elements that can be stored in the `LexOrdering`
397    /// without reallocating.
398    pub fn capacity(&self) -> usize {
399        self.exprs.capacity()
400    }
401
402    /// Truncates the `LexOrdering`, keeping only the first `len` elements.
403    /// Returns `true` if truncation made a change, `false` otherwise. Negative
404    /// cases happen in two scenarios: (1) When `len` is greater than or equal
405    /// to the number of expressions inside this `LexOrdering`, making truncation
406    /// a no-op, or (2) when `len` is `0`, making truncation impossible.
407    pub fn truncate(&mut self, len: usize) -> bool {
408        if len == 0 || len >= self.exprs.len() {
409            return false;
410        }
411        for PhysicalSortExpr { expr, .. } in self.exprs[len..].iter() {
412            self.set.remove(expr);
413        }
414        self.exprs.truncate(len);
415        true
416    }
417
418    /// Constructs a new `LexOrdering` from the given sort requirements w/o
419    /// enforcing non-degeneracy. This function is used internally and is not
420    /// meant (or safe) for external use.
421    fn construct(exprs: impl IntoIterator<Item = PhysicalSortExpr>) -> (bool, Self) {
422        let mut set = HashSet::new();
423        let exprs = exprs
424            .into_iter()
425            .filter_map(|s| set.insert(Arc::clone(&s.expr)).then_some(s))
426            .collect();
427        (!set.is_empty(), Self { exprs, set })
428    }
429}
430
431impl PartialOrd for LexOrdering {
432    /// There is a partial ordering among `LexOrdering` objects. For example, the
433    /// ordering `[a ASC]` is coarser (less) than ordering `[a ASC, b ASC]`.
434    /// If two orderings do not share a prefix, they are incomparable.
435    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
436        self.iter()
437            .zip(other.iter())
438            .all(|(lhs, rhs)| lhs == rhs)
439            .then(|| self.len().cmp(&other.len()))
440    }
441}
442
443impl<const N: usize> From<[PhysicalSortExpr; N]> for LexOrdering {
444    fn from(value: [PhysicalSortExpr; N]) -> Self {
445        // TODO: Replace this assertion with a condition on the generic parameter
446        //       when Rust supports it.
447        assert!(N > 0);
448        let (non_empty, ordering) = Self::construct(value);
449        debug_assert!(non_empty);
450        ordering
451    }
452}
453
454impl Deref for LexOrdering {
455    type Target = [PhysicalSortExpr];
456
457    fn deref(&self) -> &Self::Target {
458        self.exprs.as_slice()
459    }
460}
461
462impl Display for LexOrdering {
463    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
464        let mut first = true;
465        for sort_expr in &self.exprs {
466            if first {
467                first = false;
468            } else {
469                write!(f, ", ")?;
470            }
471            write!(f, "{sort_expr}")?;
472        }
473        Ok(())
474    }
475}
476
477impl IntoIterator for LexOrdering {
478    type Item = PhysicalSortExpr;
479    type IntoIter = IntoIter<Self::Item>;
480
481    fn into_iter(self) -> Self::IntoIter {
482        self.exprs.into_iter()
483    }
484}
485
486impl<'a> IntoIterator for &'a LexOrdering {
487    type Item = &'a PhysicalSortExpr;
488    type IntoIter = std::slice::Iter<'a, PhysicalSortExpr>;
489
490    fn into_iter(self) -> Self::IntoIter {
491        self.exprs.iter()
492    }
493}
494
495impl From<LexOrdering> for Vec<PhysicalSortExpr> {
496    fn from(ordering: LexOrdering) -> Self {
497        ordering.exprs
498    }
499}
500
501/// This object represents a lexicographical ordering requirement and contains
502/// a vector of `PhysicalSortRequirement` objects.
503///
504/// For example, a `vec![a Some(ASC), b None]` represents a lexicographical
505/// requirement that firsts imposes an ordering by column `a` in ascending
506/// order, then by column `b` in *any* (ascending or descending) order. The
507/// ordering is non-degenerate, meaning it contains at least one element, and
508/// it is duplicate-free, meaning it does not contain multiple entries for the
509/// same column.
510///
511/// Note that a `LexRequirement` need not enforce the uniqueness of its sort
512/// expressions after construction like a `LexOrdering` does, because it provides
513/// no mutation methods. If such methods become necessary, we will need to
514/// enforce uniqueness like the latter object.
515#[derive(Debug, Clone, PartialEq)]
516pub struct LexRequirement {
517    reqs: Vec<PhysicalSortRequirement>,
518}
519
520impl LexRequirement {
521    /// Creates a new [`LexRequirement`] from the given vector of sort expressions.
522    /// If the vector is empty, returns `None`.
523    pub fn new(reqs: impl IntoIterator<Item = PhysicalSortRequirement>) -> Option<Self> {
524        let (non_empty, requirements) = Self::construct(reqs);
525        non_empty.then_some(requirements)
526    }
527
528    /// Returns the leading `PhysicalSortRequirement` of the `LexRequirement`.
529    /// Note that this function does not return an `Option`, as a `LexRequirement`
530    /// is always non-degenerate (i.e. it contains at least one element).
531    pub fn first(&self) -> &PhysicalSortRequirement {
532        // Can safely `unwrap` because `LexRequirement` is non-degenerate:
533        self.reqs.first().unwrap()
534    }
535
536    /// Constructs a new `LexRequirement` from the given sort requirements w/o
537    /// enforcing non-degeneracy. This function is used internally and is not
538    /// meant (or safe) for external use.
539    fn construct(
540        reqs: impl IntoIterator<Item = PhysicalSortRequirement>,
541    ) -> (bool, Self) {
542        let mut set = HashSet::new();
543        let reqs = reqs
544            .into_iter()
545            .filter_map(|r| set.insert(Arc::clone(&r.expr)).then_some(r))
546            .collect();
547        (!set.is_empty(), Self { reqs })
548    }
549}
550
551impl<const N: usize> From<[PhysicalSortRequirement; N]> for LexRequirement {
552    fn from(value: [PhysicalSortRequirement; N]) -> Self {
553        // TODO: Replace this assertion with a condition on the generic parameter
554        //       when Rust supports it.
555        assert!(N > 0);
556        let (non_empty, requirement) = Self::construct(value);
557        debug_assert!(non_empty);
558        requirement
559    }
560}
561
562impl Deref for LexRequirement {
563    type Target = [PhysicalSortRequirement];
564
565    fn deref(&self) -> &Self::Target {
566        self.reqs.as_slice()
567    }
568}
569
570impl IntoIterator for LexRequirement {
571    type Item = PhysicalSortRequirement;
572    type IntoIter = IntoIter<Self::Item>;
573
574    fn into_iter(self) -> Self::IntoIter {
575        self.reqs.into_iter()
576    }
577}
578
579impl<'a> IntoIterator for &'a LexRequirement {
580    type Item = &'a PhysicalSortRequirement;
581    type IntoIter = std::slice::Iter<'a, PhysicalSortRequirement>;
582
583    fn into_iter(self) -> Self::IntoIter {
584        self.reqs.iter()
585    }
586}
587
588impl From<LexRequirement> for Vec<PhysicalSortRequirement> {
589    fn from(requirement: LexRequirement) -> Self {
590        requirement.reqs
591    }
592}
593
594// Cross-conversion utilities between `LexOrdering` and `LexRequirement`
595impl From<LexOrdering> for LexRequirement {
596    fn from(value: LexOrdering) -> Self {
597        // Can construct directly as `value` is non-degenerate:
598        let (non_empty, requirements) =
599            Self::construct(value.into_iter().map(Into::into));
600        debug_assert!(non_empty);
601        requirements
602    }
603}
604
605impl From<LexRequirement> for LexOrdering {
606    fn from(value: LexRequirement) -> Self {
607        // Can construct directly as `value` is non-degenerate:
608        let (non_empty, ordering) = Self::construct(value.into_iter().map(Into::into));
609        debug_assert!(non_empty);
610        ordering
611    }
612}
613
614/// Represents a plan's input ordering requirements. Vector elements represent
615/// alternative ordering requirements in the order of preference. The list of
616/// alternatives can be either hard or soft, depending on whether the operator
617/// can work without an input ordering.
618///
619/// # Invariants
620///
621/// The following always hold true for a `OrderingRequirements`:
622///
623/// 1. It is non-degenerate, meaning it contains at least one ordering. The
624///    absence of an input ordering requirement is represented by a `None` value
625///    in `ExecutionPlan` APIs, which return an `Option<OrderingRequirements>`.
626#[derive(Debug, Clone, PartialEq)]
627pub enum OrderingRequirements {
628    /// The operator is not able to work without one of these requirements.
629    Hard(Vec<LexRequirement>),
630    /// The operator can benefit from these input orderings when available,
631    /// but can still work in the absence of any input ordering.
632    Soft(Vec<LexRequirement>),
633}
634
635impl OrderingRequirements {
636    /// Creates a new instance from the given alternatives. If an empty list of
637    /// alternatives are given, returns `None`.
638    pub fn new_alternatives(
639        alternatives: impl IntoIterator<Item = LexRequirement>,
640        soft: bool,
641    ) -> Option<Self> {
642        let alternatives = alternatives.into_iter().collect::<Vec<_>>();
643        (!alternatives.is_empty()).then(|| {
644            if soft {
645                Self::Soft(alternatives)
646            } else {
647                Self::Hard(alternatives)
648            }
649        })
650    }
651
652    /// Creates a new instance with a single hard requirement.
653    pub fn new(requirement: LexRequirement) -> Self {
654        Self::Hard(vec![requirement])
655    }
656
657    /// Creates a new instance with a single soft requirement.
658    pub fn new_soft(requirement: LexRequirement) -> Self {
659        Self::Soft(vec![requirement])
660    }
661
662    /// Adds an alternative requirement to the list of alternatives.
663    pub fn add_alternative(&mut self, requirement: LexRequirement) {
664        match self {
665            Self::Hard(alts) | Self::Soft(alts) => alts.push(requirement),
666        }
667    }
668
669    /// Returns the first (i.e. most preferred) `LexRequirement` among
670    /// alternative requirements.
671    pub fn into_single(self) -> LexRequirement {
672        match self {
673            Self::Hard(mut alts) | Self::Soft(mut alts) => alts.swap_remove(0),
674        }
675    }
676
677    /// Returns a reference to the first (i.e. most preferred) `LexRequirement`
678    /// among alternative requirements.
679    pub fn first(&self) -> &LexRequirement {
680        match self {
681            Self::Hard(alts) | Self::Soft(alts) => &alts[0],
682        }
683    }
684
685    /// Returns all alternatives as a vector of `LexRequirement` objects and a
686    /// boolean value indicating softness/hardness of the requirements.
687    pub fn into_alternatives(self) -> (Vec<LexRequirement>, bool) {
688        match self {
689            Self::Hard(alts) => (alts, false),
690            Self::Soft(alts) => (alts, true),
691        }
692    }
693}
694
695impl From<LexRequirement> for OrderingRequirements {
696    fn from(requirement: LexRequirement) -> Self {
697        Self::new(requirement)
698    }
699}
700
701impl From<LexOrdering> for OrderingRequirements {
702    fn from(ordering: LexOrdering) -> Self {
703        Self::new(ordering.into())
704    }
705}
706
707impl Deref for OrderingRequirements {
708    type Target = [LexRequirement];
709
710    fn deref(&self) -> &Self::Target {
711        match &self {
712            Self::Hard(alts) | Self::Soft(alts) => alts.as_slice(),
713        }
714    }
715}
716
717impl DerefMut for OrderingRequirements {
718    fn deref_mut(&mut self) -> &mut Self::Target {
719        match self {
720            Self::Hard(alts) | Self::Soft(alts) => alts.as_mut_slice(),
721        }
722    }
723}