templar_proxy_oracle_kernel/proxy/aggregator/
mod.rs1pub mod method;
2
3#[cfg(any(feature = "borsh", feature = "schemars"))]
4use alloc::format;
5#[cfg(feature = "schemars")]
6use alloc::{boxed::Box, vec};
7
8use crate::Price;
9use method::{
10 median::{MedianHigh, MedianLow},
11 priority::Priority,
12 Aggregate,
13};
14
15use super::WeightedSource;
16
17serialize! {
18 #[derive(Debug, Clone, PartialEq, Eq)]
19 pub enum Aggregator<S> {
20 MedianLow(MedianLow<S>),
21 Priority(Priority<S>),
22 MedianHigh(MedianHigh<S>),
23 }
24}
25
26pub enum SourceIter<'a, S> {
27 Weighted(core::slice::Iter<'a, WeightedSource<S>>),
28 Plain(core::slice::Iter<'a, S>),
29}
30
31impl<S> SourceIter<'_, S> {
32 #[must_use]
33 pub fn is_empty(&self) -> bool {
34 match self {
35 Self::Weighted(iter) => iter.as_slice().is_empty(),
36 Self::Plain(iter) => iter.as_slice().is_empty(),
37 }
38 }
39}
40
41impl<'a, S> Iterator for SourceIter<'a, S> {
42 type Item = &'a S;
43
44 fn next(&mut self) -> Option<Self::Item> {
45 match self {
46 Self::Weighted(iter) => iter.next().map(|entry| &entry.source),
47 Self::Plain(iter) => iter.next(),
48 }
49 }
50
51 fn size_hint(&self) -> (usize, Option<usize>) {
52 match self {
53 Self::Weighted(iter) => iter.size_hint(),
54 Self::Plain(iter) => iter.size_hint(),
55 }
56 }
57}
58
59impl<S> ExactSizeIterator for SourceIter<'_, S> {}
60
61impl<S> Aggregator<S> {
62 pub fn median_low(entries: impl IntoIterator<Item = S>) -> Self {
63 Self::MedianLow(MedianLow::new(
64 entries.into_iter().map(|s| WeightedSource::new(s, 1)),
65 ))
66 }
67
68 pub fn median_high(entries: impl IntoIterator<Item = S>) -> Self {
69 Self::MedianHigh(MedianHigh::new(
70 entries.into_iter().map(|s| WeightedSource::new(s, 1)),
71 ))
72 }
73
74 pub fn priority(entries: impl IntoIterator<Item = S>) -> Self {
75 Self::Priority(Priority::new(entries))
76 }
77
78 pub fn name(&self) -> &'static str {
79 match self {
80 Self::MedianLow(_) => "MedianLow",
81 Self::Priority(_) => "Priority",
82 Self::MedianHigh(_) => "MedianHigh",
83 }
84 }
85
86 pub fn sources(&self) -> SourceIter<'_, S> {
87 match self {
88 Self::MedianLow(inner) => SourceIter::Weighted(inner.sources.iter()),
89 Self::Priority(inner) => SourceIter::Plain(inner.sources.iter()),
90 Self::MedianHigh(inner) => SourceIter::Weighted(inner.sources.iter()),
91 }
92 }
93}
94
95impl<S> Aggregate<S> for Aggregator<S> {
96 fn aggregate<I>(&self, prices: I) -> Result<Price, method::Error>
97 where
98 I: IntoIterator<Item = Option<Price>>,
99 I::IntoIter: ExactSizeIterator<Item = Option<Price>>,
100 {
101 match self {
102 Self::MedianLow(inner) => inner.aggregate(prices),
103 Self::Priority(inner) => inner.aggregate(prices),
104 Self::MedianHigh(inner) => inner.aggregate(prices),
105 }
106 }
107}