1use serde::{Deserialize, Serialize};
2use std::collections::BTreeMap;
3use std::convert::TryFrom;
4use std::fs::{read_to_string, OpenOptions};
5use std::io::Write;
6use std::path::Path;
7
8use crate::errors::{ConverterError, DeserializationError, SerializationError};
9
10#[derive(Clone, Debug, Deserialize, Serialize)]
11#[serde(untagged)]
12pub enum Type {
13 Integer(i64),
14 ByteString(String),
15 List(Vec<Type>),
16 Dictionary(BTreeMap<String, Type>),
17}
18
19impl TryFrom<Type> for String {
20 type Error = ConverterError;
21
22 fn try_from(value: Type) -> Result<Self, Self::Error> {
23 match value {
24 Type::ByteString(s) => Ok(s),
25 _ => Err(ConverterError::InvalidString),
26 }
27 }
28}
29
30impl TryFrom<&Type> for String {
31 type Error = ConverterError;
32
33 fn try_from(value: &Type) -> Result<Self, Self::Error> {
34 match value {
35 Type::ByteString(s) => Ok(s.to_string()),
36 _ => Err(ConverterError::InvalidString),
37 }
38 }
39}
40
41impl TryFrom<Type> for i64 {
42 type Error = ConverterError;
43
44 fn try_from(value: Type) -> Result<Self, Self::Error> {
45 match value {
46 Type::Integer(i) => Ok(i),
47 _ => Err(ConverterError::InvalidInteger),
48 }
49 }
50}
51
52impl Type {
53 pub fn from_json(s: &String) -> Result<Type, DeserializationError> {
54 match serde_json::from_str::<Type>(s) {
55 Err(_) => Err(DeserializationError::JsonDeserializationError),
56 Ok(t) => Ok(t),
57 }
58 }
59
60 pub fn to_json(&self) -> Result<String, SerializationError> {
61 match serde_json::to_string(self) {
62 Err(_) => Err(SerializationError::JsonSerializationError),
63 Ok(str) => Ok(str),
64 }
65 }
66
67 pub fn load_from_json<P>(path: P) -> Result<Type, DeserializationError>
68 where
69 P: AsRef<Path>,
70 {
71 match read_to_string(path) {
72 Err(_) => return Err(DeserializationError::FileError),
73 Ok(json_str) => Type::from_json(&json_str),
74 }
75 }
76
77 pub fn save_to_json<P>(&self, path: P) -> Result<(), SerializationError>
78 where
79 P: AsRef<Path>,
80 {
81 let json = self.to_json()?;
82 let file = OpenOptions::new().write(true).create_new(true).open(path);
83
84 match file {
85 Err(_) => return Err(SerializationError::FileError),
86 Ok(mut file) => match writeln!(file, "{}", json) {
87 Ok(_) => Ok(()),
88 Err(_) => Err(SerializationError::FileSerializationError),
89 },
90 }
91 }
92
93 pub fn get(&self, key: String) -> Result<&Type, ConverterError> {
94 match self {
95 Type::Dictionary(d) => match d.get(&key) {
96 Some(t) => Ok(t),
97 None => Err(ConverterError::InvalidDictionary),
98 },
99 _ => Err(ConverterError::InvalidDictionary),
100 }
101 }
102}