use serde::{Deserialize, Deserializer};
use crate::core::wire::RawNumI64;
#[derive(Deserialize)]
pub(crate) struct V10Result {
#[serde(rename = "incomeStatementHistory")]
pub(crate) income_statement_history: Option<IncomeHistoryNode>,
#[serde(rename = "incomeStatementHistoryQuarterly")]
pub(crate) income_statement_history_quarterly: Option<IncomeHistoryNode>,
#[serde(rename = "balanceSheetHistory")]
pub(crate) balance_sheet_history: Option<BalanceHistoryNode>,
#[serde(rename = "balanceSheetHistoryQuarterly")]
pub(crate) balance_sheet_history_quarterly: Option<BalanceHistoryNode>,
#[serde(rename = "cashflowStatementHistory")]
pub(crate) cashflow_statement_history: Option<CashflowHistoryNode>,
#[serde(rename = "cashflowStatementHistoryQuarterly")]
pub(crate) cashflow_statement_history_quarterly: Option<CashflowHistoryNode>,
pub(crate) earnings: Option<EarningsNode>,
#[serde(rename = "calendarEvents")]
pub(crate) calendar_events: Option<CalendarEventsNode>,
}
#[derive(Deserialize)]
pub(crate) struct IncomeHistoryNode {
#[serde(rename = "incomeStatementHistory")]
pub(crate) income_statement_history: Option<Vec<IncomeRowNode>>,
}
#[derive(Deserialize)]
pub(crate) struct IncomeRowNode {
#[serde(rename = "endDate")]
pub(crate) end_date: Option<RawDate>,
#[serde(rename = "totalRevenue")]
pub(crate) total_revenue: Option<RawNum>,
#[serde(rename = "grossProfit")]
pub(crate) gross_profit: Option<RawNum>,
#[serde(rename = "operatingIncome")]
pub(crate) operating_income: Option<RawNum>,
#[serde(rename = "netIncome")]
pub(crate) net_income: Option<RawNum>,
}
#[derive(Deserialize)]
pub(crate) struct BalanceHistoryNode {
#[serde(rename = "balanceSheetStatements")]
pub(crate) balance_sheet_statements: Option<Vec<BalanceRowNode>>,
}
#[derive(Deserialize)]
pub(crate) struct BalanceRowNode {
#[serde(rename = "endDate")]
pub(crate) end_date: Option<RawDate>,
#[serde(rename = "totalAssets")]
pub(crate) total_assets: Option<RawNum>,
#[serde(rename = "totalLiab")]
pub(crate) total_liab: Option<RawNum>,
#[serde(rename = "totalStockholderEquity")]
pub(crate) total_stockholder_equity: Option<RawNum>,
pub(crate) cash: Option<RawNum>,
#[serde(rename = "longTermDebt")]
pub(crate) long_term_debt: Option<RawNum>,
#[serde(rename = "commonStockSharesIssued")]
pub(crate) shares_outstanding: Option<RawNumI64>,
}
#[derive(Deserialize)]
pub(crate) struct CashflowHistoryNode {
#[serde(rename = "cashflowStatements")]
pub(crate) cashflow_statements: Option<Vec<CashflowRowNode>>,
}
#[derive(Deserialize)]
pub(crate) struct CashflowRowNode {
#[serde(rename = "endDate")]
pub(crate) end_date: Option<RawDate>,
#[serde(rename = "totalCashFromOperatingActivities")]
pub(crate) total_cash_from_operating_activities: Option<RawNum>,
#[serde(rename = "capitalExpenditures")]
pub(crate) capital_expenditures: Option<RawNum>,
#[serde(rename = "freeCashflow")]
pub(crate) free_cashflow: Option<RawNum>,
#[serde(rename = "netIncome")]
pub(crate) net_income: Option<RawNum>,
}
#[derive(Deserialize)]
pub(crate) struct EarningsNode {
#[serde(rename = "financialsChart")]
pub(crate) financials_chart: Option<FinancialsChartNode>,
#[serde(rename = "earningsChart")]
pub(crate) earnings_chart: Option<EarningsChartNode>,
}
#[derive(Deserialize)]
pub(crate) struct FinancialsChartNode {
pub(crate) yearly: Option<Vec<FinancialYearNode>>,
pub(crate) quarterly: Option<Vec<FinancialQuarterNode>>,
}
#[derive(Deserialize)]
pub(crate) struct FinancialYearNode {
pub(crate) date: Option<i64>,
pub(crate) revenue: Option<RawNum>,
pub(crate) earnings: Option<RawNum>,
}
#[derive(Deserialize)]
pub(crate) struct FinancialQuarterNode {
pub(crate) date: Option<String>,
pub(crate) revenue: Option<RawNum>,
pub(crate) earnings: Option<RawNum>,
}
#[derive(Deserialize)]
pub(crate) struct EarningsChartNode {
pub(crate) quarterly: Option<Vec<EpsQuarterNode>>,
}
#[derive(Deserialize)]
pub(crate) struct EpsQuarterNode {
pub(crate) date: Option<String>,
pub(crate) actual: Option<RawNum>,
pub(crate) estimate: Option<RawNum>,
}
#[derive(Deserialize)]
pub(crate) struct CalendarEventsNode {
pub(crate) earnings: Option<CalendarEarningsNode>,
}
#[derive(Deserialize)]
pub(crate) struct CalendarEarningsNode {
#[serde(rename = "earningsDate")]
pub(crate) earnings_date: Option<Vec<RawDate>>,
#[serde(rename = "exDividendDate")]
pub(crate) ex_dividend_date: Option<RawDate>,
#[serde(rename = "dividendDate")]
pub(crate) dividend_date: Option<RawDate>,
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct TimeseriesEnvelope {
pub(crate) timeseries: Option<TimeseriesResult>,
}
#[derive(Deserialize)]
pub(crate) struct TimeseriesResult {
pub(crate) result: Option<Vec<TimeseriesData>>,
}
#[derive(Deserialize)]
pub(crate) struct TimeseriesData {
pub(crate) timestamp: Option<Vec<i64>>,
#[allow(dead_code)]
meta: serde_json::Value,
#[serde(flatten)]
pub(crate) values: std::collections::HashMap<String, Vec<TimeseriesValue>>,
}
#[derive(Deserialize)]
pub(crate) struct TimeseriesValue {
#[serde(rename = "reportedValue")]
pub(crate) reported_value: Option<RawNumU64>,
}
fn de_u64_from_any_number<'de, D>(deserializer: D) -> Result<Option<u64>, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
#[serde(untagged)]
enum AnyNumber {
U64(u64),
F64(f64),
}
match Option::<AnyNumber>::deserialize(deserializer)? {
Some(AnyNumber::U64(u)) => Ok(Some(u)),
Some(AnyNumber::F64(f)) => {
if f.fract() == 0.0 && f >= 0.0 {
Ok(Some(f as u64))
} else {
Err(serde::de::Error::custom(format!(
"cannot convert float {} to u64",
f
)))
}
}
None => Ok(None),
}
}
#[derive(Deserialize, Clone, Copy)]
pub(crate) struct RawNumU64 {
#[serde(deserialize_with = "de_u64_from_any_number")]
pub(crate) raw: Option<u64>,
}
#[derive(Deserialize, Clone, Copy)]
pub(crate) struct RawDate {
pub(crate) raw: Option<i64>,
}
#[derive(Deserialize, Clone, Copy)]
pub(crate) struct RawNum {
pub(crate) raw: Option<f64>,
}
pub(crate) fn raw_num(n: RawNum) -> Option<f64> {
n.raw
}