Skip to main content

finance_query/models/filings/
filing_index.rs

1//! EDGAR filing index models.
2//!
3//! Models for the filing directory index at:
4//! `https://www.sec.gov/Archives/edgar/data/{cik}/{accession}/index.json`.
5
6use serde::{Deserialize, Deserializer, Serialize};
7
8/// The wire value is always a JSON string ("24417" or "" for directory
9/// entries with no size, e.g. the filing's own index pages).
10fn deserialize_size<'de, D>(deserializer: D) -> Result<Option<u64>, D::Error>
11where
12    D: Deserializer<'de>,
13{
14    let s = String::deserialize(deserializer)?;
15    Ok(s.parse().ok())
16}
17
18/// Filing index response for a specific EDGAR accession.
19#[derive(Debug, Clone, Serialize, Deserialize)]
20#[non_exhaustive]
21pub struct EdgarFilingIndex {
22    /// Directory listing metadata.
23    #[serde(default)]
24    pub directory: EdgarFilingIndexDirectory,
25}
26
27/// Directory metadata for an EDGAR filing.
28#[derive(Debug, Clone, Serialize, Deserialize, Default)]
29#[non_exhaustive]
30pub struct EdgarFilingIndexDirectory {
31    /// Listing of files for the filing.
32    #[serde(default)]
33    pub item: Vec<EdgarFilingIndexItem>,
34}
35
36/// Single file entry within an EDGAR filing index.
37#[derive(Debug, Clone, Serialize, Deserialize)]
38#[non_exhaustive]
39pub struct EdgarFilingIndexItem {
40    /// File name (e.g., "aapl-20240928.htm").
41    pub name: String,
42
43    /// File-icon class from the directory listing (e.g. "text.gif"), not the
44    /// exhibit or form type — SEC EDGAR doesn't expose that here.
45    #[serde(default, rename = "type")]
46    pub item_type: String,
47
48    /// File size in bytes; `None` for entries with no size (e.g. the
49    /// filing's own index pages).
50    #[serde(default, deserialize_with = "deserialize_size")]
51    pub size: Option<u64>,
52}