places/history_sync/
record.rs
1use crate::{history_sync::ServerVisitTimestamp, types::UnknownFields};
6use serde::Deserialize;
7use serde_derive::*;
8use sync_guid::Guid as SyncGuid;
9
10#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
11#[serde(rename_all = "camelCase")]
12pub struct HistoryRecordVisit {
13 pub date: ServerVisitTimestamp,
14 #[serde(rename = "type")]
15 pub transition: u8,
16
17 #[serde(flatten)]
18 pub unknown_fields: UnknownFields,
19}
20
21#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
22#[serde(rename_all = "camelCase")]
23pub struct HistoryRecord {
24 pub id: SyncGuid,
26
27 #[serde(default)]
28 #[serde(deserialize_with = "deserialize_nonull_string")]
29 #[serde(skip_serializing_if = "String::is_empty")]
30 pub title: String,
31
32 pub hist_uri: String,
33
34 pub visits: Vec<HistoryRecordVisit>,
35
36 #[serde(flatten)]
37 pub unknown_fields: UnknownFields,
38}
39
40fn deserialize_nonull_string<'de, D>(deserializer: D) -> Result<String, D::Error>
41where
42 D: serde::Deserializer<'de>,
43{
44 Ok(match <Option<String>>::deserialize(deserializer)? {
45 Some(s) => s,
46 None => "".to_string(),
47 })
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53
54 #[test]
55 fn test_null_title() {
56 let json = serde_json::json!({
60 "id": "foo",
61 "title": null,
62 "histUri": "https://example.com",
63 "visits": [],
64 });
65
66 let rec = serde_json::from_value::<HistoryRecord>(json).expect("should deser");
67 assert!(rec.title.is_empty());
68 }
69
70 #[test]
71 fn test_missing_title() {
72 let json = serde_json::json!({
73 "id": "foo",
74 "histUri": "https://example.com",
75 "visits": [],
76 });
77
78 let rec = serde_json::from_value::<HistoryRecord>(json).expect("should deser");
79 assert!(rec.title.is_empty());
80 }
81}