1use chrono::serde::ts_seconds;
2use chrono::{DateTime, Utc};
3use serde::{Deserialize, Serialize};
4
5#[derive(Serialize, Deserialize, Debug)]
6#[serde(untagged)]
7pub enum Item {
8 DeletedItem {
9 id: u32,
10 deleted: bool,
11 #[serde(with = "ts_seconds")]
12 time: DateTime<Utc>,
13 #[serde(rename = "type")]
14 type_: String,
15 },
16 LiveItem {
17 by: String,
18 #[serde(default)]
19 dead: bool,
20 id: u32,
21 #[serde(with = "ts_seconds")]
22 time: DateTime<Utc>,
23 #[serde(flatten)]
24 variant: ItemVariant,
25 },
26}
27
28#[derive(Serialize, Deserialize, Debug)]
29#[serde(tag = "type")]
30#[serde(rename_all = "lowercase")]
31pub enum ItemVariant {
32 Story {
33 #[serde(default)]
34 descendants: i32,
35 #[serde(default)]
36 kids: Vec<u32>,
37 score: i32,
38 title: String,
39 url: Option<String>,
41 text: Option<String>,
42 },
43 Comment {
44 #[serde(default)]
45 kids: Vec<u32>,
46 parent: u32,
47 text: String,
48 },
49 Job {
50 score: i32,
51 text: Option<String>,
52 title: String,
53 url: Option<String>,
54 },
55 Poll {
56 descendants: i32,
57 #[serde(default)]
58 kids: Vec<u32>,
59 #[serde(default)]
60 parts: Vec<u32>,
61 score: i32,
62 title: String,
63 },
64 PollOpt {
65 poll: u32,
66 score: i32,
67 text: String,
68 },
69}
70
71#[cfg(test)]
72mod tests {
73 use crate::Item;
74 use matches::assert_matches;
75 use serde_json;
76
77 #[test]
78 fn test_simple_parse() {
79 let json = r#"
80 {
81 "by": "gzer0",
82 "dead": false,
83 "id": 27164354,
84 "time": 1620568471,
85 "type": "comment",
86 "kids": [],
87 "parent": 27164095,
88 "text": "A message goes here"
89 }
90 "#;
91 assert_matches!(serde_json::from_str(json), Ok(Item::LiveItem { .. }))
92 }
93}