finance_query/providers/adapter/dispatch.rs
1//! [`ProviderAdapter`]: the accessors dispatch walks to reach a capability.
2
3use super::super::Capability;
4use crate::error::Result;
5
6use super::ProviderCore;
7use super::equity::*;
8use super::markets::*;
9
10/// A configured provider as seen by [`crate::ProviderSet`] dispatch: lifecycle
11/// plus one `as_*` accessor per capability. Override an accessor to
12/// `Some(self)` for each capability trait the provider implements.
13///
14/// [`capabilities`](Self::capabilities) is derived from which accessors are
15/// overridden, so a provider cannot advertise a capability it does not serve.
16#[async_trait::async_trait]
17pub trait ProviderAdapter: ProviderCore {
18 /// Initialize this provider. Called once during construction.
19 async fn initialize(&self) -> Result<()> {
20 Ok(())
21 }
22
23 /// Best-effort estimate of remaining rate-limit budget — tokens
24 /// currently available in this provider's own token bucket, for
25 /// [`crate::Providers::health`]. Peeking never consumes a
26 /// token.
27 ///
28 /// `None` by default: providers with no local rate limiter to peek (e.g.
29 /// Yahoo) or whose singleton hasn't been initialized yet return `None`
30 /// rather than a misleading number.
31 fn rate_limit_remaining(&self) -> Option<f64> {
32 None
33 }
34
35 /// Whether requests go to an origin set with
36 /// [`ProvidersBuilder::endpoint`](crate::ProvidersBuilder::endpoint).
37 ///
38 /// `false` by default, and the builder rejects an endpoint for a provider
39 /// that would ignore it.
40 fn accepts_endpoint(&self) -> bool {
41 false
42 }
43
44 /// Whether this provider's API-key budget follows
45 /// [`ProvidersBuilder::requests_per_minute`](crate::ProvidersBuilder::requests_per_minute).
46 ///
47 /// `false` by default, and the builder rejects a budget for a provider that
48 /// would ignore it.
49 fn accepts_request_budget(&self) -> bool {
50 false
51 }
52
53 /// Override to `Some(self)` to serve [`crate::Capability::QUOTE`].
54 fn as_quote(&self) -> Option<&dyn QuoteProvider> {
55 None
56 }
57 /// Override to `Some(self)` to serve [`crate::Capability::CHART`].
58 fn as_chart(&self) -> Option<&dyn ChartProvider> {
59 None
60 }
61 /// Override to `Some(self)` to serve [`crate::Capability::FUNDAMENTALS`].
62 fn as_fundamentals(&self) -> Option<&dyn FundamentalsProvider> {
63 None
64 }
65 /// Override to `Some(self)` to serve [`crate::Capability::CORPORATE`].
66 fn as_corporate(&self) -> Option<&dyn CorporateProvider> {
67 None
68 }
69 /// Override to `Some(self)` to serve [`crate::Capability::OPTIONS`].
70 fn as_options(&self) -> Option<&dyn OptionsProvider> {
71 None
72 }
73 /// Override to `Some(self)` to serve [`crate::Capability::FILINGS`].
74 fn as_filings(&self) -> Option<&dyn FilingsProvider> {
75 None
76 }
77 /// Override to `Some(self)` to serve [`crate::Capability::DISCOVERY`].
78 fn as_discovery(&self) -> Option<&dyn DiscoveryProvider> {
79 None
80 }
81 /// Override to `Some(self)` to serve [`crate::Capability::CALENDAR`].
82 fn as_calendar(&self) -> Option<&dyn CalendarProvider> {
83 None
84 }
85 /// Override to `Some(self)` to serve [`crate::Capability::MARKET`].
86 fn as_market(&self) -> Option<&dyn MarketProvider> {
87 None
88 }
89 /// Override to `Some(self)` to serve [`crate::Capability::CRYPTO`].
90 fn as_crypto(&self) -> Option<&dyn CryptoProvider> {
91 None
92 }
93 /// Override to `Some(self)` to serve [`crate::Capability::ECONOMIC`].
94 fn as_economic(&self) -> Option<&dyn EconomicProvider> {
95 None
96 }
97 /// Override to `Some(self)` to serve [`crate::Capability::FOREX`].
98 fn as_forex(&self) -> Option<&dyn ForexProvider> {
99 None
100 }
101 /// Override to `Some(self)` to serve [`crate::Capability::INDICES`].
102 fn as_indices(&self) -> Option<&dyn IndicesProvider> {
103 None
104 }
105 /// Override to `Some(self)` to serve [`crate::Capability::FUTURES`].
106 fn as_futures(&self) -> Option<&dyn FuturesProvider> {
107 None
108 }
109 /// Override to `Some(self)` to serve [`crate::Capability::COMMODITIES`].
110 fn as_commodities(&self) -> Option<&dyn CommoditiesProvider> {
111 None
112 }
113
114 /// Derived from the accessors — a provider supports a capability iff the
115 /// matching `as_*` accessor returns `Some`. Never override.
116 fn capabilities(&self) -> Capability {
117 let mut caps = Capability::NONE;
118 if self.as_quote().is_some() {
119 caps = caps | Capability::QUOTE;
120 }
121 if self.as_chart().is_some() {
122 caps = caps | Capability::CHART;
123 }
124 if self.as_fundamentals().is_some() {
125 caps = caps | Capability::FUNDAMENTALS;
126 }
127 if self.as_corporate().is_some() {
128 caps = caps | Capability::CORPORATE;
129 }
130 if self.as_options().is_some() {
131 caps = caps | Capability::OPTIONS;
132 }
133 if self.as_filings().is_some() {
134 caps = caps | Capability::FILINGS;
135 }
136 if self.as_market().is_some() {
137 caps = caps | Capability::MARKET;
138 }
139 if self.as_discovery().is_some() {
140 caps = caps | Capability::DISCOVERY;
141 }
142 if self.as_calendar().is_some() {
143 caps = caps | Capability::CALENDAR;
144 }
145 #[cfg(any(
146 feature = "alphavantage",
147 feature = "binance",
148 feature = "crypto",
149 feature = "defi",
150 feature = "fmp",
151 feature = "gdelt",
152 feature = "kraken",
153 feature = "polygon"
154 ))]
155 if self.as_crypto().is_some() {
156 caps = caps | Capability::CRYPTO;
157 }
158 #[cfg(any(
159 feature = "alphavantage",
160 feature = "bls",
161 feature = "fiscaldata",
162 feature = "fred",
163 feature = "polygon",
164 feature = "worldbank"
165 ))]
166 if self.as_economic().is_some() {
167 caps = caps | Capability::ECONOMIC;
168 }
169 #[cfg(any(
170 feature = "alphavantage",
171 feature = "fmp",
172 feature = "frankfurter",
173 feature = "gdelt",
174 feature = "polygon"
175 ))]
176 if self.as_forex().is_some() {
177 caps = caps | Capability::FOREX;
178 }
179 if self.as_indices().is_some() {
180 caps = caps | Capability::INDICES;
181 }
182 if self.as_futures().is_some() {
183 caps = caps | Capability::FUTURES;
184 }
185 if self.as_commodities().is_some() {
186 caps = caps | Capability::COMMODITIES;
187 }
188 caps
189 }
190}