1use super::{AuthorFilter, KeyFilter, Query, QueryKind, SortBy};
4use crate::SignedEntry;
5
6#[derive(Debug)]
8pub enum IndexKind {
9 AuthorKey {
10 range: AuthorFilter,
11 key_filter: KeyFilter,
12 },
13 KeyAuthor {
14 range: KeyFilter,
15 author_filter: AuthorFilter,
16 latest_per_key: bool,
17 },
18}
19
20impl From<&Query> for IndexKind {
21 fn from(query: &Query) -> Self {
22 match &query.kind {
23 QueryKind::Flat(details) => match (&query.filter_author, details.sort_by) {
24 (AuthorFilter::Any, SortBy::KeyAuthor) => IndexKind::KeyAuthor {
25 range: query.filter_key.clone(),
26 author_filter: AuthorFilter::Any,
27 latest_per_key: false,
28 },
29 _ => IndexKind::AuthorKey {
30 range: query.filter_author.clone(),
31 key_filter: query.filter_key.clone(),
32 },
33 },
34 QueryKind::SingleLatestPerKey(_) => IndexKind::KeyAuthor {
35 range: query.filter_key.clone(),
36 author_filter: query.filter_author.clone(),
37 latest_per_key: true,
38 },
39 }
40 }
41}
42
43#[derive(Debug, Default)]
47pub struct LatestPerKeySelector(Option<SignedEntry>);
48
49#[allow(clippy::large_enum_variant)]
50pub enum SelectorRes {
51 Finished,
53 Continue,
55 Some(SignedEntry),
57}
58
59impl LatestPerKeySelector {
60 pub fn push(&mut self, entry: Option<SignedEntry>) -> SelectorRes {
64 let Some(entry) = entry else {
65 return match self.0.take() {
66 Some(entry) => SelectorRes::Some(entry),
67 None => SelectorRes::Finished,
68 };
69 };
70 match self.0.take() {
71 None => {
72 self.0 = Some(entry);
73 SelectorRes::Continue
74 }
75 Some(last) if last.key() == entry.key() => {
76 if entry.timestamp() > last.timestamp() {
77 self.0 = Some(entry);
78 } else {
79 self.0 = Some(last);
80 }
81 SelectorRes::Continue
82 }
83 Some(last) => {
84 self.0 = Some(entry);
85 SelectorRes::Some(last)
86 }
87 }
88 }
89}