1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
pub mod error;
pub use tiny_serde_derive::Serialize;

use std::collections::HashMap;

#[derive(Clone, Debug)]
pub enum Value {
    Null,
    Boolean(bool),
    Number(f64),
    String(String),
    Array(Vec<Value>),
    Object(HashMap<String, Value>),
}

impl ToString for Value {
    fn to_string(&self) -> String {
        match self {
            Self::Null => "null".to_string(),
            Self::Boolean(b) => match b {
                true => "true",
                false => "false",
            }
            .to_string(),
            Self::Number(nb) => nb.to_string(),
            Self::String(value) => {
                format!("\"{value}\"")
            }
            Self::Array(array) => {
                let mut final_value = "[".to_string();
                let last_index = array.len() - 1;
                for (i, value) in array.iter().enumerate() {
                    if i < last_index {
                        final_value += &format!("{},", value.to_string());
                    } else {
                        final_value += &format!("{}", value.to_string());
                    }
                }
                final_value += "]";
                final_value
            }
            Self::Object(node) => {
                let mut final_value = "{".to_string();
                let last_index = node.len() - 1;
                let mut i = 0;
                for (key, value) in node.iter() {
                    if i < last_index {
                        final_value += &format!("\"{key}\":{},", value.to_string());
                    } else {
                        final_value += &format!("\"{key}\":{}", value.to_string());
                    }
                    i += 1;
                }
                final_value += "}";
                final_value
            }
        }
    }
}

pub trait Serialize {
    fn serialize(&self) -> Value;
}

pub fn to_string<S: Serialize>(value: &S) -> String {
    value.serialize().to_string()
}

fn patch_control_characters(input: &str) -> String {
    let input = input
        .chars()
        .map(|c| {
            if c == '\\' {
                r#"\\"#.to_string()
            } else if c == '"' {
                r#"\""#.to_string()
            } else {
                c.to_string()
            }
        })
        .collect::<String>();
    input
}

impl Serialize for String {
    fn serialize(&self) -> Value {
        let value = patch_control_characters(self);
        Value::String(value)
    }
}

impl<S: Serialize> Serialize for Option<S> {
    fn serialize(&self) -> Value {
        match self {
            Some(value) => value.serialize(),
            None => Value::Null,
        }
    }
}

impl Serialize for bool {
    fn serialize(&self) -> Value {
        Value::Boolean(*self)
    }
}

impl Serialize for f64 {
    fn serialize(&self) -> Value {
        Value::Number(*self)
    }
}

impl Serialize for Vec<Value> {
    fn serialize(&self) -> Value {
        Value::Array(self.clone())
    }
}

impl Serialize for HashMap<String, Value> {
    fn serialize(&self) -> Value {
        Value::Object(self.clone())
    }
}