rester/
persistence.rs

1use crate::Method;
2
3use serde::{Deserialize, Serialize};
4
5use std::fs::File;
6use std::io::{BufReader, Write};
7use std::path::Path;
8
9#[derive(Serialize, Deserialize, Debug)]
10pub struct KeyValuePair {
11    pub key: String,
12    pub value: String,
13}
14
15impl KeyValuePair {
16    pub fn to_string(&self) -> String {
17        format!("{:}:{:}", self.key, self.value)
18    }
19}
20
21#[derive(Serialize, Deserialize, Debug)]
22pub struct Request {
23    pub key: String,
24    pub method: Method,
25    pub url: String,
26    // Headers is a list for deterministic
27    // JSON ordering. Versus an object which an editor may
28    // re-order.
29    #[serde(skip_serializing_if = "Option::is_none")]
30    pub headers: Option<Vec<KeyValuePair>>,
31    pub body: Option<String>,
32}
33
34impl Request {
35    pub fn headers_to_string(&self) -> String {
36        match &self.headers {
37            None => "".to_string(),
38            Some(headers) => {
39                let strings: Vec<String> = headers.iter().map(|i| i.to_string()).collect();
40                strings.join("\r\n")
41            }
42        }
43    }
44}
45
46pub struct RequestBuilder {
47    key: String,
48    method: Method,
49    url: Option<String>,
50    body: Option<String>,
51    headers: Option<String>,
52}
53
54impl RequestBuilder {
55    pub fn new(req_key: &str) -> RequestBuilder {
56        RequestBuilder {
57            key: req_key.to_string(),
58            method: Method::GET,
59            url: None,
60            headers: None,
61            body: None,
62        }
63    }
64
65    pub fn headers(&mut self, headers: &str) -> &Self {
66        self.headers = Some(headers.to_string());
67        self
68    }
69
70    pub fn url(&mut self, url: &str) -> &Self {
71        self.url = Some(url.to_string());
72        self
73    }
74
75    pub fn method(&mut self, method: Method) -> &Self {
76        self.method = method;
77        self
78    }
79
80    pub fn body(&mut self, body: &str) -> &Self {
81        self.body = Some(body.to_string());
82        self
83    }
84
85    pub fn build(self) -> Request {
86        let headers = match self.headers {
87            None => None,
88            Some(header_string) => {
89                let headers_strings: Vec<&str> = header_string.split("\r\n").collect();
90                let mut parsed_headers: Vec<KeyValuePair> = Vec::new();
91
92                for entry in headers_strings {
93                    if let Some((key, value)) = entry.split_once(":") {
94                        parsed_headers.push(KeyValuePair {
95                            key: key.trim().to_string(),
96                            value: value.trim().to_string(),
97                        })
98                    }
99                }
100                if parsed_headers.is_empty() {
101                    None
102                } else {
103                    Some(parsed_headers)
104                }
105            }
106        };
107
108        Request {
109            key: self.key,
110            method: self.method,
111            url: self.url.expect("Must set URL."),
112            headers,
113            body: self.body,
114        }
115    }
116}
117
118#[derive(Serialize, Deserialize, Debug)]
119pub struct RequestCollection {
120    pub requests: Vec<Request>,
121}
122
123impl RequestCollection {
124    pub fn new() -> Self {
125        RequestCollection {
126            requests: Vec::new(),
127        }
128    }
129
130    pub fn add_request(&mut self, request: Request) {
131        let req_key = request.key.as_str();
132        match self.requests.iter().position(|item| item.key == req_key) {
133            None => {
134                self.requests.push(request);
135            }
136            Some(index) => {
137                let _ = std::mem::replace(&mut self.requests[index], request);
138            }
139        };
140    }
141
142    pub fn remove_request(&mut self, index: usize) {
143        if index < self.requests.len() {
144            self.requests.remove(index);
145        }
146    }
147
148    pub fn save(&self) {
149        let serialized = serde_json::to_string_pretty(&self.requests);
150        info!("Serialized: {:?}", serialized);
151        let file = File::create("requests.json");
152        if let Ok(mut file) = file {
153            if let Err(err) = file.write_all(serialized.unwrap().as_bytes()) {
154                error!("Error writing file {:?}", err);
155            }
156        }
157    }
158
159    pub fn load() -> Self {
160        if Path::new("requests.json").exists() {
161            match File::open("requests.json") {
162                Ok(file) => {
163                    let reader = BufReader::new(file);
164
165                    // Read the JSON contents of the file as an instance of `User`.
166                    match serde_json::from_reader(reader) {
167                        Ok(collection) => {
168                            return Self {
169                                requests: collection,
170                            };
171                        }
172                        _ => {}
173                    }
174                }
175                Err(_) => {}
176            }
177        }
178        Self::new()
179    }
180}