hackernews_types/
lib.rs

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        // Ask-hn and stories are the same fucking structure. Urgh. Need to differencate this somehow.
40        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}