1use std::error::Error;
2use std::fs::File;
3use std::io::BufRead;
4use std::path::Path;
5
6use serde::Deserialize;
7
8#[derive(Deserialize, Debug)]
9#[serde(deny_unknown_fields)]
10#[allow(dead_code)]
11pub struct Vote {
12 #[serde(rename = "Date")]
13 pub date: String,
14
15 #[serde(rename = "Link")]
16 pub link: String,
17
18 #[serde(rename = "OptionText")]
19 pub option_text: String,
20}
21
22#[derive(Deserialize, Debug)]
23#[serde(deny_unknown_fields)]
24#[allow(dead_code)]
25pub struct SearchQuery {
26 #[serde(rename = "Time")]
27 pub time: String,
28
29 #[serde(rename = "Search Query")]
30 pub search_query: String,
31}
32
33#[derive(Deserialize, Debug)]
34#[serde(deny_unknown_fields)]
35#[allow(dead_code)]
36pub struct Message {
37 #[serde(rename = "CONVERSATION ID")]
38 pub conversation_id: String,
39
40 #[serde(rename = "CONVERSATION TITLE")]
41 pub conversation_title: String,
42
43 #[serde(rename = "FROM")]
44 pub from: String,
45
46 #[serde(rename = "SENDER PROFILE URL")]
47 pub sender_profile_url: String,
48
49 #[serde(rename = "TO")]
50 pub to: String,
51
52 #[serde(rename = "RECIPIENT PROFILE URLS")]
53 pub recipient_profile_urls: String,
54
55 #[serde(rename = "DATE")]
56 pub date: String,
57
58 #[serde(rename = "SUBJECT")]
59 pub subject: String,
60
61 #[serde(rename = "CONTENT")]
62 pub content: String,
63
64 #[serde(rename = "FOLDER")]
65 pub folder: String,
66
67 #[serde(rename = "IS MESSAGE DRAFT")]
68 pub is_message_draft: String,
69}
70
71#[derive(Deserialize, Debug)]
72#[serde(deny_unknown_fields)]
73#[allow(dead_code)]
74pub struct Connection {
75 #[serde(rename = "First Name")]
76 pub first_name: String,
77
78 #[serde(rename = "Last Name")]
79 pub last_name: String,
80
81 #[serde(rename = "URL")]
82 pub url: String,
83
84 #[serde(rename = "Email Address")]
85 pub email_address: String,
86
87 #[serde(rename = "Company")]
88 pub company: String,
89
90 #[serde(rename = "Position")]
91 pub position: String,
92
93 #[serde(rename = "Connected On")]
94 pub connected_on: String,
95}
96
97#[derive(Deserialize, Debug)]
98#[serde(deny_unknown_fields)]
99#[allow(dead_code)]
100pub struct Invitation {
101 #[serde(rename = "From")]
102 pub from: String,
103
104 #[serde(rename = "To")]
105 pub to: String,
106
107 #[serde(rename = "Sent At")]
108 pub sent_at: String,
109
110 #[serde(rename = "Message")]
111 pub message: String,
112
113 #[serde(rename = "Direction")]
114 pub direction: String,
115
116 #[serde(rename = "inviterProfileUrl")]
117 pub inviter_profile_url: String,
118
119 #[serde(rename = "inviteeProfileUrl")]
120 pub invitee_profile_url: String,
121}
122
123#[derive(Deserialize, Debug)]
124#[serde(deny_unknown_fields)]
125#[allow(dead_code)]
126pub struct Skill {
127 #[serde(rename = "Name")]
128 pub name: String,
129}
130
131#[derive(Deserialize, Debug)]
132#[serde(deny_unknown_fields)]
133#[allow(dead_code)]
134pub struct Share {
135 #[serde(rename = "Date")]
136 pub date: String,
137
138 #[serde(rename = "ShareLink")]
139 pub share_link: String,
140
141 #[serde(rename = "ShareCommentary")]
142 pub share_commentary: String,
143
144 #[serde(rename = "SharedUrl")]
145 pub shared_url: String,
146
147 #[serde(rename = "MediaUrl")]
148 pub media_url: String,
149
150 #[serde(rename = "Visibility")]
151 pub visibility: String,
152}
153
154#[derive(Deserialize, Debug)]
155#[serde(deny_unknown_fields)]
156#[allow(dead_code)]
157pub struct Contact {
158 #[serde(rename = "Source")]
159 pub source: String,
160
161 #[serde(rename = "FirstName")]
162 pub first_name: String,
163
164 #[serde(rename = "LastName")]
165 pub last_name: String,
166
167 #[serde(rename = "Companies")]
168 pub companies: String,
169
170 #[serde(rename = "Title")]
171 pub title: String,
172
173 #[serde(rename = "Emails")]
174 pub emails: String,
175
176 #[serde(rename = "PhoneNumbers")]
177 pub phone_numbers: String,
178
179 #[serde(rename = "CreatedAt")]
180 pub created_at: String,
181
182 #[serde(rename = "Addresses")]
183 pub addresses: String,
184
185 #[serde(rename = "Sites")]
186 pub sites: String,
187
188 #[serde(rename = "InstantMessageHandles")]
189 pub instant_message_handles: String,
190
191 #[serde(rename = "FullName")]
192 pub full_name: String,
193
194 #[serde(rename = "Birthday")]
195 pub birthday: String,
196
197 #[serde(rename = "Location")]
198 pub location: String,
199
200 #[serde(rename = "BookmarkedAt")]
201 pub bookmarked_at: String,
202
203 #[serde(rename = "Profiles")]
204 pub profiles: String,
205}
206
207macro_rules! read_file {
208 ($name:ident, $struct:ty, $file:expr) => {
209 pub fn $name(path: &Path) -> Result<Vec<$struct>, Box<dyn Error>> {
210 let filepath = path.join($file);
211 let mut records: Vec<$struct> = vec![];
212 let fh = File::open(&filepath)?;
213 let mut rdr = csv::Reader::from_reader(fh);
214 for result in rdr.deserialize() {
215 let record: $struct = result?;
216 records.push(record);
217 }
218 Ok(records)
219 }
220 };
221}
222
223read_file!(read_contacts_file, Contact, "Contacts.csv");
224read_file!(read_skills_file, Skill, "Skills.csv");
225read_file!(read_shares_file, Share, "Shares.csv");
226read_file!(read_invitations_file, Invitation, "Invitations.csv");
227read_file!(read_messages_file, Message, "messages.csv");
228read_file!(read_votes_file, Vote, "Votes.csv");
229
230pub fn read_connections_file(path: &Path) -> Result<Vec<Connection>, Box<dyn Error>> {
231 let filepath = path.join("Connections.csv");
232 let mut records: Vec<Connection> = vec![];
233 let fh = File::open(&filepath)?;
234 let mut br = std::io::BufReader::new(&fh);
235
236 for _ in 0..3 {
241 br.skip_until(b'\n')
242 .expect("expecting Notes before the header");
243 }
244
245 let mut rdr = csv::Reader::from_reader(br);
246 for result in rdr.deserialize() {
247 let record: Connection = result?;
248 records.push(record);
249 }
250 Ok(records)
251}
252
253pub fn read_search_queries_file(path: &Path) -> Result<Vec<SearchQuery>, Box<dyn Error>> {
254 let filepath = path.join("SearchQueries.csv");
255 let mut records: Vec<SearchQuery> = vec![];
256 let fh = File::open(&filepath)?;
257 let mut rdr = csv::Reader::from_reader(fh);
258 for result in rdr.deserialize() {
259 let record: SearchQuery = result?;
260 records.push(record);
261 }
262 Ok(records)
263}
264
265#[cfg(test)]
266mod tests {
267
268 #[test]
269 fn it_works() {
270 let result = 42;
271 assert_eq!(result, 42);
272 }
273}