mastodon_async/helpers/
toml.rs

1use std::{
2    fs::{File, OpenOptions},
3    io::{Read, Write},
4    path::Path,
5};
6
7use tomlcrate;
8
9use crate::{Data, Result};
10
11/// Attempts to deserialize a Data struct from a string
12pub fn from_str(s: &str) -> Result<Data> {
13    Ok(tomlcrate::from_str(s)?)
14}
15
16/// Attempts to deserialize a Data struct from a slice of bytes
17pub fn from_slice(s: &[u8]) -> Result<Data> {
18    from_str(&String::from_utf8(s.into())?)
19}
20
21/// Attempts to deserialize a Data struct from something that implements
22/// the std::io::Read trait
23pub fn from_reader<R: Read>(mut r: R) -> Result<Data> {
24    let mut buffer = Vec::new();
25    r.read_to_end(&mut buffer)?;
26    from_slice(&buffer)
27}
28
29/// Attempts to deserialize a Data struct from a file
30pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Data> {
31    let path = path.as_ref();
32    let file = File::open(path)?;
33    from_reader(file)
34}
35
36/// Attempts to serialize a Data struct to a String
37pub fn to_string(data: &Data) -> Result<String> {
38    Ok(tomlcrate::to_string_pretty(data)?)
39}
40
41/// Attempts to serialize a Data struct to a Vec of bytes
42pub fn to_vec(data: &Data) -> Result<Vec<u8>> {
43    Ok(tomlcrate::to_string(data)?.as_bytes().into())
44}
45
46/// Attempts to serialize a Data struct to something that implements the
47/// std::io::Write trait
48pub fn to_writer<W: Write>(data: &Data, mut writer: W) -> Result<()> {
49    writer.write_all(tomlcrate::to_string(data)?.as_bytes())?;
50    Ok(())
51}
52
53/// Attempts to serialize a Data struct to a file
54///
55/// When opening the file, this will set the `.write(true)` and
56/// `.truncate(true)` options, use the next method for more
57/// fine-grained control
58pub fn to_file<P: AsRef<Path>>(data: &Data, path: P) -> Result<()> {
59    let mut options = OpenOptions::new();
60    options.create(true).write(true).truncate(true);
61    to_file_with_options(data, path, options)
62}
63
64/// Attempts to serialize a Data struct to a file
65pub fn to_file_with_options<P: AsRef<Path>>(
66    data: &Data,
67    path: P,
68    options: OpenOptions,
69) -> Result<()> {
70    let path = path.as_ref();
71    let file = options.open(path)?;
72    to_writer(data, file)?;
73    Ok(())
74}
75
76#[cfg(test)]
77mod tests {
78    use super::*;
79    use std::{fs::OpenOptions, io::Cursor};
80    use tempfile::{tempdir, NamedTempFile};
81
82    const DOC: &str = indoc!(
83        r#"
84            base = "https://example.com"
85            client_id = "adbc01234"
86            client_secret = "0987dcba"
87            redirect = "urn:ietf:wg:oauth:2.0:oob"
88            token = "fedc5678"
89    "#
90    );
91
92    #[test]
93    fn test_from_str() {
94        let desered = from_str(DOC).expect("Couldn't deserialize Data");
95        assert_eq!(
96            desered,
97            Data {
98                base: "https://example.com".into(),
99                client_id: "adbc01234".into(),
100                client_secret: "0987dcba".into(),
101                redirect: "urn:ietf:wg:oauth:2.0:oob".into(),
102                token: "fedc5678".into(),
103            }
104        );
105    }
106    #[test]
107    fn test_from_slice() {
108        let doc = DOC.as_bytes();
109        let desered = from_slice(doc).expect("Couldn't deserialize Data");
110        assert_eq!(
111            desered,
112            Data {
113                base: "https://example.com".into(),
114                client_id: "adbc01234".into(),
115                client_secret: "0987dcba".into(),
116                redirect: "urn:ietf:wg:oauth:2.0:oob".into(),
117                token: "fedc5678".into(),
118            }
119        );
120    }
121    #[test]
122    fn test_from_reader() {
123        let doc = DOC.as_bytes();
124        let doc = Cursor::new(doc);
125        let desered = from_reader(doc).expect("Couldn't deserialize Data");
126        assert_eq!(
127            desered,
128            Data {
129                base: "https://example.com".into(),
130                client_id: "adbc01234".into(),
131                client_secret: "0987dcba".into(),
132                redirect: "urn:ietf:wg:oauth:2.0:oob".into(),
133                token: "fedc5678".into(),
134            }
135        );
136    }
137    #[test]
138    fn test_from_file() {
139        let mut datafile = NamedTempFile::new().expect("Couldn't create tempfile");
140        write!(&mut datafile, "{}", DOC).expect("Couldn't write Data to file");
141        let desered = from_file(datafile.path()).expect("Couldn't deserialize Data");
142        assert_eq!(
143            desered,
144            Data {
145                base: "https://example.com".into(),
146                client_id: "adbc01234".into(),
147                client_secret: "0987dcba".into(),
148                redirect: "urn:ietf:wg:oauth:2.0:oob".into(),
149                token: "fedc5678".into(),
150            }
151        );
152    }
153    #[test]
154    fn test_to_string() {
155        let data = Data {
156            base: "https://example.com".into(),
157            client_id: "adbc01234".into(),
158            client_secret: "0987dcba".into(),
159            redirect: "urn:ietf:wg:oauth:2.0:oob".into(),
160            token: "fedc5678".into(),
161        };
162        let s = to_string(&data).expect("Couldn't serialize Data");
163        let desered = from_str(&s).expect("Couldn't deserialize Data");
164        assert_eq!(data, desered);
165    }
166    #[test]
167    fn test_to_vec() {
168        let data = Data {
169            base: "https://example.com".into(),
170            client_id: "adbc01234".into(),
171            client_secret: "0987dcba".into(),
172            redirect: "urn:ietf:wg:oauth:2.0:oob".into(),
173            token: "fedc5678".into(),
174        };
175        let v = to_vec(&data).expect("Couldn't write to vec");
176        let desered = from_slice(&v).expect("Couldn't deserialize data");
177        assert_eq!(data, desered);
178    }
179    #[test]
180    fn test_to_writer() {
181        let data = Data {
182            base: "https://example.com".into(),
183            client_id: "adbc01234".into(),
184            client_secret: "0987dcba".into(),
185            redirect: "urn:ietf:wg:oauth:2.0:oob".into(),
186            token: "fedc5678".into(),
187        };
188        let mut buffer = Vec::new();
189        to_writer(&data, &mut buffer).expect("Couldn't write to writer");
190        let reader = Cursor::new(buffer);
191        let desered = from_reader(reader).expect("Couldn't deserialize Data");
192        assert_eq!(data, desered);
193    }
194    #[test]
195    fn test_to_file() {
196        let data = Data {
197            base: "https://example.com".into(),
198            client_id: "adbc01234".into(),
199            client_secret: "0987dcba".into(),
200            redirect: "urn:ietf:wg:oauth:2.0:oob".into(),
201            token: "fedc5678".into(),
202        };
203        let tempdir = tempdir().expect("Couldn't create tempdir");
204        let filename = tempdir.path().join("mastodon-data.toml");
205        to_file(&data, &filename).expect("Couldn't write to file");
206        let desered = from_file(&filename).expect("Couldn't deserialize Data");
207        assert_eq!(data, desered);
208    }
209    #[test]
210    fn test_to_file_with_options() {
211        let data = Data {
212            base: "https://example.com".into(),
213            client_id: "adbc01234".into(),
214            client_secret: "0987dcba".into(),
215            redirect: "urn:ietf:wg:oauth:2.0:oob".into(),
216            token: "fedc5678".into(),
217        };
218        let file = NamedTempFile::new().expect("Couldn't create tempfile");
219        let mut options = OpenOptions::new();
220        options.write(true).create(false).truncate(true);
221        to_file_with_options(&data, file.path(), options).expect("Couldn't write to file");
222        let desered = from_file(file.path()).expect("Couldn't deserialize Data");
223        assert_eq!(data, desered);
224    }
225}