vector/api/schema/
sort.rs

1use std::cmp::Ordering;
2
3use async_graphql::{Enum, InputObject, InputType};
4use itertools::{
5    FoldWhile::{Continue, Done},
6    Itertools,
7};
8
9use crate::api::schema::{
10    components::{
11        sink::SinksSortFieldName, source::SourcesSortFieldName, transform::TransformsSortFieldName,
12        ComponentsSortFieldName,
13    },
14    metrics::source::file::FileSourceMetricFilesSortFieldName,
15};
16
17#[derive(Enum, Copy, Clone, Default, PartialEq, Eq)]
18pub enum Direction {
19    #[default]
20    Asc,
21    Desc,
22}
23
24#[derive(InputObject)]
25#[graphql(concrete(name = "ComponentsSortField", params(ComponentsSortFieldName)))]
26#[graphql(concrete(name = "SourcesSortField", params(SourcesSortFieldName)))]
27#[graphql(concrete(name = "TransformsSortField", params(TransformsSortFieldName)))]
28#[graphql(concrete(name = "SinksSortField", params(SinksSortFieldName)))]
29#[graphql(concrete(
30    name = "FileSourceMetricFilesSortField",
31    params(FileSourceMetricFilesSortFieldName)
32))]
33pub struct SortField<T: InputType> {
34    pub field: T,
35    #[graphql(default_with = "Direction::default()")]
36    pub direction: Direction,
37}
38
39/// Defines a type as sortable by a given field
40pub trait SortableByField<T: InputType> {
41    fn sort(&self, rhs: &Self, field: &T) -> Ordering;
42}
43
44/// Performs an in-place sort against a slice of `Sortable<T>`, with the provided [`SortField<T>`]s
45pub fn by_fields<T: InputType>(f: &mut [impl SortableByField<T>], sort_fields: &[SortField<T>]) {
46    f.sort_by(|a, b| {
47        sort_fields
48            .iter()
49            .fold_while(Ordering::Equal, |cmp, f| match cmp {
50                Ordering::Equal => {
51                    let cmp = a.sort(b, &f.field);
52                    Continue(match f.direction {
53                        Direction::Desc => cmp.reverse(),
54                        _ => cmp,
55                    })
56                }
57                _ => Done(cmp),
58            })
59            .into_inner()
60    });
61}