finance_query/models/lookup/
response.rs1use super::LookupQuote;
6use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, Deserialize)]
10#[serde(rename_all = "camelCase")]
11struct RawLookupResponse {
12 finance: Option<RawFinanceResult>,
13}
14
15#[derive(Debug, Clone, Deserialize)]
16#[serde(rename_all = "camelCase")]
17struct RawFinanceResult {
18 result: Option<Vec<RawLookupResult>>,
19 #[allow(dead_code)]
20 error: Option<serde_json::Value>,
21}
22
23#[derive(Debug, Clone, Deserialize)]
24#[serde(rename_all = "camelCase")]
25struct RawLookupResult {
26 documents: Option<Vec<LookupQuote>>,
27 start: Option<i32>,
28 count: Option<i32>,
29}
30
31#[derive(Debug, Clone, Serialize, Deserialize)]
33#[non_exhaustive]
34#[serde(rename_all = "camelCase")]
35pub struct LookupResults {
36 #[serde(default)]
38 pub quotes: Vec<LookupQuote>,
39 #[serde(skip_serializing_if = "Option::is_none")]
41 pub start: Option<i32>,
42 #[serde(skip_serializing_if = "Option::is_none")]
44 pub count: Option<i32>,
45}
46
47impl LookupResults {
48 pub fn from_json(value: serde_json::Value) -> Result<Self, serde_json::Error> {
66 let raw: RawLookupResponse = serde_json::from_value(value)?;
67
68 let (quotes, start, count) = raw
69 .finance
70 .and_then(|f| f.result)
71 .and_then(|r| r.into_iter().next())
72 .map(|result| {
73 (
74 result.documents.unwrap_or_default(),
75 result.start,
76 result.count,
77 )
78 })
79 .unwrap_or_default();
80
81 Ok(LookupResults {
82 quotes,
83 start,
84 count,
85 })
86 }
87
88 pub fn quotes(&self) -> &[LookupQuote] {
90 &self.quotes
91 }
92
93 pub fn result_count(&self) -> i32 {
95 self.count.unwrap_or(0)
96 }
97
98 pub fn is_empty(&self) -> bool {
100 self.quotes.is_empty()
101 }
102}
103
104#[cfg(feature = "dataframe")]
105impl LookupResults {
106 pub fn to_dataframe(&self) -> ::polars::prelude::PolarsResult<::polars::prelude::DataFrame> {
108 LookupQuote::vec_to_dataframe(&self.quotes)
109 }
110}