cooplan_config_reader/
reader.rs1use std::io::{Error, ErrorKind};
2use serde::Deserialize;
3use serde_json::Value;
4
5pub async fn try_read<T: for<'de> Deserialize<'de>>(file_path: &str) -> Result<T, Error> {
6 let value = match tokio::fs::read_to_string(file_path).await {
7 Ok(file_content) => try_deserialize(file_content)?,
8 Err(error) => {
9 return Err(error);
10 }
11 };
12
13 Ok(value)
14}
15
16fn try_deserialize<T: for<'de> Deserialize<'de>>(file_content: String) -> Result<T, Error> {
17 match serde_json::from_str::<Value>(&file_content) {
18 Ok(value) => match serde_json::from_value::<T>(value) {
19 Ok(value) => Ok(value),
20 Err(error) => {
21 return Err(Error::new(
22 ErrorKind::InvalidData,
23 format!("failed to deserialize file's content: {}", error),
24 ));
25 }
26 },
27 Err(error) => {
28 Err(Error::new(
29 ErrorKind::InvalidData,
30 format!("failed to deserialize file's content: {}", error),
31 ))
32 }
33 }
34}
35
36#[cfg(test)]
37#[test]
38pub fn converts_string_into_expected_value() {
39 #[derive(Deserialize)]
40 struct Example {
41 a: u32,
42 b: String,
43 c: bool,
44 }
45
46 let first_json = r#"{"a": 1, "b": "2", "c": true}"#;
47 let second_json = r#"{"a": 3, "b": "4", "c": false}"#;
48
49 let first = try_deserialize::<Example>(first_json.to_string()).unwrap();
50 let second = try_deserialize::<Example>(second_json.to_string()).unwrap();
51
52 assert_eq!(first.a, 1);
53 assert_eq!(first.b, "2");
54 assert_eq!(first.c, true);
55
56 assert_eq!(second.a, 3);
57 assert_eq!(second.b, "4");
58 assert_eq!(second.c, false);
59}