Skip to main content

ferric_fred/
ids.rs

1/// A FRED series identifier, e.g. `GNPCA` or `UNRATE`.
2///
3/// A newtype over `String` so a series id can't be silently swapped for another
4/// kind of identifier or an arbitrary string (see ADR-0005). Construction does
5/// no validation for now — FRED rejects malformed ids — but the newtype gives
6/// us a place to add it later without changing call sites.
7#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
8#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
9pub struct SeriesId(String);
10
11impl SeriesId {
12    /// Wrap a string as a [`SeriesId`].
13    pub fn new(id: impl Into<String>) -> Self {
14        Self(id.into())
15    }
16
17    /// Borrow the identifier as a string slice.
18    pub fn as_str(&self) -> &str {
19        &self.0
20    }
21}
22
23impl std::fmt::Display for SeriesId {
24    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25        f.write_str(&self.0)
26    }
27}
28
29impl From<&str> for SeriesId {
30    fn from(s: &str) -> Self {
31        Self(s.to_owned())
32    }
33}
34
35impl From<String> for SeriesId {
36    fn from(s: String) -> Self {
37        Self(s)
38    }
39}
40
41/// A GeoFRED / Maps series-group identifier, e.g. `1223` — the group of
42/// regional series a `geofred/regional/data` request pulls a cross-section from.
43///
44/// A newtype over `String`: FRED transmits it as a string (`"series_group":
45/// "1223"`) even though it reads as a number, so — unlike the numeric
46/// [`CategoryId`]/[`ReleaseId`] `u32` newtypes — it stays string-backed to match
47/// the wire (ADR-0005). Construction does no validation.
48#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
49#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
50pub struct SeriesGroupId(String);
51
52impl SeriesGroupId {
53    /// Wrap a string as a [`SeriesGroupId`].
54    pub fn new(id: impl Into<String>) -> Self {
55        Self(id.into())
56    }
57
58    /// Borrow the identifier as a string slice.
59    pub fn as_str(&self) -> &str {
60        &self.0
61    }
62}
63
64impl std::fmt::Display for SeriesGroupId {
65    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66        f.write_str(&self.0)
67    }
68}
69
70impl From<&str> for SeriesGroupId {
71    fn from(s: &str) -> Self {
72        Self(s.to_owned())
73    }
74}
75
76impl From<String> for SeriesGroupId {
77    fn from(s: String) -> Self {
78        Self(s)
79    }
80}
81
82/// A FRED category identifier — a numeric node in the category tree (the root is
83/// [`CategoryId::ROOT`], id `0`).
84///
85/// A `Copy` newtype over `u32` so a category id can't be silently swapped for a
86/// parent id, a count, or an arbitrary number (ADR-0005). `#[serde(transparent)]`
87/// carries it on the wire as the bare integer FRED sends.
88#[derive(
89    Debug, Clone, Copy, PartialEq, Eq, Hash, Default, serde::Serialize, serde::Deserialize,
90)]
91#[serde(transparent)]
92#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
93pub struct CategoryId(u32);
94
95impl CategoryId {
96    /// The root of the FRED category tree (id `0`).
97    pub const ROOT: Self = Self(0);
98
99    /// Wrap a numeric id as a [`CategoryId`].
100    pub fn new(id: u32) -> Self {
101        Self(id)
102    }
103
104    /// The underlying numeric id.
105    pub fn get(self) -> u32 {
106        self.0
107    }
108}
109
110impl std::fmt::Display for CategoryId {
111    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112        write!(f, "{}", self.0)
113    }
114}
115
116impl From<u32> for CategoryId {
117    fn from(id: u32) -> Self {
118        Self(id)
119    }
120}
121
122/// A FRED release identifier — the numeric id of a data release (a publication
123/// such as "Gross Domestic Product").
124///
125/// A `Copy` newtype over `u32`, mirroring [`CategoryId`]; `#[serde(transparent)]`
126/// carries it as the bare integer FRED sends (ADR-0005).
127#[derive(
128    Debug, Clone, Copy, PartialEq, Eq, Hash, Default, serde::Serialize, serde::Deserialize,
129)]
130#[serde(transparent)]
131#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
132pub struct ReleaseId(u32);
133
134impl ReleaseId {
135    /// Wrap a numeric id as a [`ReleaseId`].
136    pub fn new(id: u32) -> Self {
137        Self(id)
138    }
139
140    /// The underlying numeric id.
141    pub fn get(self) -> u32 {
142        self.0
143    }
144}
145
146impl std::fmt::Display for ReleaseId {
147    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
148        write!(f, "{}", self.0)
149    }
150}
151
152impl From<u32> for ReleaseId {
153    fn from(id: u32) -> Self {
154        Self(id)
155    }
156}
157
158/// A FRED release-table element identifier — the numeric id of a node in a
159/// release's table tree (a section, table, or series row; see
160/// `fred/release/tables`).
161///
162/// A `Copy` newtype over `u32`, mirroring [`ReleaseId`]; `#[serde(transparent)]`
163/// carries it as the bare integer FRED sends (ADR-0005). `Ord` lets the table
164/// deserializer order its roots deterministically by id.
165#[derive(
166    Debug,
167    Clone,
168    Copy,
169    PartialEq,
170    Eq,
171    PartialOrd,
172    Ord,
173    Hash,
174    Default,
175    serde::Serialize,
176    serde::Deserialize,
177)]
178#[serde(transparent)]
179#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
180pub struct ReleaseElementId(u32);
181
182impl ReleaseElementId {
183    /// Wrap a numeric id as a [`ReleaseElementId`].
184    pub fn new(id: u32) -> Self {
185        Self(id)
186    }
187
188    /// The underlying numeric id.
189    pub fn get(self) -> u32 {
190        self.0
191    }
192}
193
194impl std::fmt::Display for ReleaseElementId {
195    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
196        write!(f, "{}", self.0)
197    }
198}
199
200impl From<u32> for ReleaseElementId {
201    fn from(id: u32) -> Self {
202        Self(id)
203    }
204}
205
206/// A FRED source identifier — the numeric id of a data source (the organization
207/// that produces a release, e.g. the Bureau of Economic Analysis).
208///
209/// A `Copy` newtype over `u32`, mirroring [`ReleaseId`]; `#[serde(transparent)]`
210/// carries it as the bare integer FRED sends (ADR-0005).
211#[derive(
212    Debug, Clone, Copy, PartialEq, Eq, Hash, Default, serde::Serialize, serde::Deserialize,
213)]
214#[serde(transparent)]
215#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
216pub struct SourceId(u32);
217
218impl SourceId {
219    /// Wrap a numeric id as a [`SourceId`].
220    pub fn new(id: u32) -> Self {
221        Self(id)
222    }
223
224    /// The underlying numeric id.
225    pub fn get(self) -> u32 {
226        self.0
227    }
228}
229
230impl std::fmt::Display for SourceId {
231    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
232        write!(f, "{}", self.0)
233    }
234}
235
236impl From<u32> for SourceId {
237    fn from(id: u32) -> Self {
238        Self(id)
239    }
240}